From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- .gitignore | 9 + BENCHES | 330 + INSTALL | 99 + Makefile | 157 + Makefile.def-samples/MakeDef.cad | 25 + Makefile.def-samples/MakeDef.dos | 32 + Makefile.def-samples/MakeDef.dpmi | 30 + .../Makefile.def-alpha-dec-osf13.2 | 27 + .../Makefile.def-alpha-dec-osf14.0 | 27 + .../Makefile.def-alpha-unknown-linux2.x.x | 25 + .../Makefile.def-hppa-hp-hpux-10.0 | 28 + Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.0 | 26 + .../Makefile.def-i386-unknown-dpmi | 30 + .../Makefile.def-i386-unknown-linux2.x.x | 27 + .../Makefile.def-i386-unknown-msdos | 32 + Makefile.def-samples/Makefile.def-i386-unknown-os2 | 33 + .../Makefile.def-i386-unknown-os2-visualage | 31 + .../Makefile.def-i386-unknown-win32 | 28 + Makefile.def-samples/Makefile.def-m68k-pcs-munix3 | 25 + .../Makefile.def-m68k-sun-netbsd1.2 | 28 + .../Makefile.def-mips-dec-netbsd1.2 | 28 + .../Makefile.def-mips-dec-ultrix4.3 | 25 + Makefile.def-samples/Makefile.def-mips-sgi-irix6.2 | 25 + .../Makefile.def-mips64-sgi-irix6.4 | 25 + Makefile.def-samples/Makefile.def-rs6k-ibm-aix41 | 28 + .../Makefile.def-sparc-sun-solaris2.x | 24 + .../Makefile.def-sparc-sun-sunos4.1.3 | 25 + .../Makefile.def-vax-dec-ultrix4.1 | 25 + Makefile.def.tmpl | 25 + Makefile.dos | 120 + Makefile.os2 | 100 + README | 98 + README.DOS | 26 + README.KR | 55 + README.LANGS | 197 + README.OS2 | 26 + TODO | 6 + a2k.c | 193 + addcr.c | 14 + as.c | 2985 +++++ as.h | 11 + as.res | 983 ++ as1750.c | 1295 ++ as1750.h | 18 + asl.1 | 377 + asl.def | 2 + asmallg.c | 1341 +++ asmallg.h | 21 + asmcode.c | 239 + asmcode.h | 27 + asmdebug.c | 320 + asmdebug.h | 20 + asmdef.c | 315 + asmdef.h | 400 + asmfnums.c | 167 + asmfnums.h | 29 + asmif.c | 433 + asmif.h | 37 + asminclist.c | 116 + asminclist.h | 19 + asmitree.c | 277 + asmitree.h | 65 + asmmac.c | 503 + asmmac.h | 105 + asmpars.c | 3822 ++++++ asmpars.h | 207 + asmrelocs.c | 133 + asmrelocs.h | 22 + asmsub.c | 1526 +++ asmsub.h | 166 + bincmp.c | 46 + bpemu.c | 239 + bpemu.h | 33 + changelog | 729 ++ chardefs.h | 237 + chunks.c | 228 + chunks.h | 44 + cmdarg.c | 222 + cmdarg.h | 46 + cmdarg.res | 24 + code166.c | 1697 +++ code166.h | 11 + code16c5x.c | 448 + code16c5x.h | 12 + code16c8x.c | 472 + code16c8x.h | 11 + code17c4x.c | 521 + code17c4x.h | 11 + code29k.c | 887 ++ code29k.h | 11 + code3201x.c | 553 + code3201x.h | 11 + code3202x.c | 1122 ++ code3202x.h | 9 + code3203x.c | 1511 +++ code3203x.h | 11 + code3205x.c | 1852 +++ code3205x.h | 9 + code3206x.c | 2313 ++++ code3206x.h | 12 + code370.c | 1117 ++ code370.h | 11 + code4004.c | 503 + code4004.h | 11 + code4500.c | 397 + code4500.h | 11 + code47c00.c | 1126 ++ code47c00.h | 11 + code48.c | 998 ++ code48.h | 11 + code51.c | 2304 ++++ code51.h | 11 + code53c8xx.c | 1055 ++ code53c8xx.h | 11 + code56k.c | 2566 ++++ code56k.h | 11 + code601.c | 2017 ++++ code601.h | 11 + code65.c | 736 ++ code65.h | 11 + code68.c | 847 ++ code68.h | 11 + code6804.c | 451 + code6804.h | 11 + code6805.c | 786 ++ code6805.h | 11 + code6809.c | 1318 +++ code6809.h | 11 + code6812.c | 1143 ++ code6812.h | 11 + code6816.c | 1073 ++ code6816.h | 11 + code68k.c | 4428 +++++++ code68k.h | 11 + code7000.c | 1315 +++ code7000.h | 11 + code75k0.c | 1436 +++ code75k0.h | 11 + code7700.c | 1304 ++ code7700.h | 11 + code7720.c | 587 + code7720.h | 11 + code77230.c | 1024 ++ code77230.h | 11 + code78c10.c | 978 ++ code78c10.h | 11 + code78k0.c | 1228 ++ code78k0.h | 11 + code8008.c | 356 + code8008.h | 11 + code85.c | 423 + code85.h | 11 + code86.c | 2600 ++++ code86.h | 11 + code87c800.c | 1316 +++ code87c800.h | 11 + code8x30x.c | 559 + code8x30x.h | 11 + code90c141.c | 1293 ++ code90c141.h | 11 + code96.c | 1253 ++ code96.h | 11 + code960.c | 767 ++ code960.h | 11 + code96c141.c | 2331 ++++ code96c141.h | 11 + code97c241.c | 2190 ++++ code97c241.h | 11 + code9900.c | 685 ++ code9900.h | 11 + codeace.c | 767 ++ codeace.h | 11 + codeavr.c | 784 ++ codeavr.h | 11 + codecop8.c | 727 ++ codecop8.h | 11 + codeflt1750.c | 158 + codeflt1750.h | 7 + codefmc8.c | 1017 ++ codefmc8.h | 11 + codeh8_3.c | 1707 +++ codeh8_3.h | 11 + codeh8_5.c | 1510 +++ codeh8_5.h | 11 + codem16.c | 2819 +++++ codem16.h | 11 + codem16c.c | 2360 ++++ codem16c.h | 11 + codemcore.c | 806 ++ codemcore.h | 11 + codemsp.c | 539 + codemsp.h | 11 + codepseudo.c | 1246 ++ codepseudo.h | 37 + codesc14xxx.c | 441 + codesc14xxx.h | 16 + codescmp.c | 326 + codescmp.h | 11 + codest6.c | 634 + codest6.h | 11 + codest7.c | 878 ++ codest7.h | 11 + codest9.c | 1878 +++ codest9.h | 11 + codetms7.c | 954 ++ codetms7.h | 11 + codevars.c | 14 + codevars.h | 12 + codexa.c | 1975 ++++ codexa.h | 11 + codez8.c | 856 ++ codez8.h | 11 + codez80.c | 2814 +++++ codez80.h | 11 + datatypes.h | 55 + doc_DE/Makefile | 37 + doc_DE/as.tex | 11792 +++++++++++++++++++ doc_DE/dina4.sty | 135 + doc_DE/pscomm.tex | 16 + doc_DE/pscpu.tex | 420 + doc_DE/tabids.tex | 33 + doc_DE/taborg1.tex | 48 + doc_DE/taborg2.tex | 49 + doc_DE/taborg3.tex | 51 + doc_DE/taborg4.tex | 11 + doc_EN/Makefile | 36 + doc_EN/as.tex | 11521 ++++++++++++++++++ endian.c | 333 + endian.h | 54 + equs.h | 6 + fileformat.h | 40 + findhyphen.c | 270 + findhyphen.h | 9 + grhyph.c | 569 + grhyph.h | 12 + header.res | 6 + headids.c | 124 + headids.h | 28 + hex.c | 72 + hex.h | 19 + include/80c50x.inc | 257 + include/80c552.inc | 228 + include/bitfuncs.inc | 85 + include/ctype.inc | 94 + include/h8_3048.inc | 560 + include/reg166.inc | 780 ++ include/reg251.inc | 225 + include/reg29k.inc | 127 + include/reg53x.inc | 344 + include/reg683xx.inc | 700 ++ include/reg7000.inc | 120 + include/reg78k0.inc | 245 + include/reg96.inc | 610 + include/regavr.inc | 329 + include/regcop8.inc | 242 + include/reghc12.inc | 228 + include/regm16c.inc | 421 + include/regmsp.inc | 227 + include/regst9.inc | 624 + include/regz380.inc | 68 + include/stddef04.inc | 54 + include/stddef16.inc | 188 + include/stddef17.inc | 116 + include/stddef18.inc | 262 + include/stddef2x.inc | 53 + include/stddef37.inc | 527 + include/stddef3x.inc | 96 + include/stddef47.inc | 279 + include/stddef51.inc | 374 + include/stddef56k.inc | 69 + include/stddef5x.inc | 109 + include/stddef60.inc | 674 ++ include/stddef62.inc | 147 + include/stddef75.inc | 699 ++ include/stddef87.inc | 218 + include/stddef90.inc | 129 + include/stddef96.inc | 170 + include/stddefxa.inc | 405 + include/stddefz8.inc | 56 + install.bat | 24 + install.cmd | 24 + install.sh | 66 + ioerrs.c | 193 + ioerrs.h | 13 + ioerrs.res | 212 + makedefs.files | 35 + makedefs.src | 53 + makedefs.str | 41 + marks.asm | 29 + nlmessages.c | 210 + nlmessages.h | 24 + nls.c | 644 + nls.h | 60 + objdefs.dos | 14 + objdefs.unix | 14 + p2bin.1 | 241 + p2bin.c | 536 + p2bin.res | 46 + p2hex.1 | 288 + p2hex.c | 987 ++ p2hex.res | 77 + pascstyle.h | 17 + pbind.1 | 145 + pbind.c | 182 + pbind.res | 34 + plist.1 | 84 + plist.c | 169 + plist.res | 57 + reltypes.c | 9 + rescomp.c | 433 + specchars.h | 13 + stdhandl.c | 110 + stdhandl.h | 21 + stdinc.h | 45 + stringlists.c | 151 + stringlists.h | 43 + strutil.c | 461 + strutil.h | 70 + sysdefs.h | 774 ++ tests/t_166/asflags | 0 tests/t_166/t_166.asm | 232 + tests/t_166/t_166.doc | 5 + tests/t_166/t_166.ori | Bin 0 -> 534 bytes tests/t_16c5x/asflags | 0 tests/t_16c5x/t_16c5x.asm | 45 + tests/t_16c5x/t_16c5x.doc | 5 + tests/t_16c5x/t_16c5x.ori | Bin 0 -> 70 bytes tests/t_16c84/asflags | 0 tests/t_16c84/t_16c84.asm | 53 + tests/t_16c84/t_16c84.doc | 5 + tests/t_16c84/t_16c84.ori | Bin 0 -> 90 bytes tests/t_17c42/asflags | 0 tests/t_17c42/t_17c42.asm | 66 + tests/t_17c42/t_17c42.doc | 5 + tests/t_17c42/t_17c42.ori | Bin 0 -> 112 bytes tests/t_251/asflags | 0 tests/t_251/t_251.asm | 399 + tests/t_251/t_251.doc | 5 + tests/t_251/t_251.ori | Bin 0 -> 1035 bytes tests/t_296/asflags | 0 tests/t_296/t_296.asm | 132 + tests/t_296/t_296.doc | 6 + tests/t_296/t_296.ori | Bin 0 -> 463 bytes tests/t_29k/asflags | 0 tests/t_29k/t_29k.asm | 80 + tests/t_29k/t_29k.doc | 5 + tests/t_29k/t_29k.ori | Bin 0 -> 220 bytes tests/t_32/asflags | 0 tests/t_32/t_32.asm | 39 + tests/t_32/t_32.doc | 6 + tests/t_32/t_32.ori | Bin 0 -> 134 bytes tests/t_3201x/asflags | 0 tests/t_3201x/t_3201x.asm | 74 + tests/t_3201x/t_3201x.doc | 5 + tests/t_3201x/t_3201x.ori | Bin 0 -> 148 bytes tests/t_3203x/asflags | 0 tests/t_3203x/t_3203x.asm | 271 + tests/t_3203x/t_3203x.doc | 5 + tests/t_3203x/t_3203x.ori | Bin 0 -> 816 bytes tests/t_3205x/asflags | 0 tests/t_3205x/t_3205x.asm | 499 + tests/t_3205x/t_3205x.doc | 7 + tests/t_3205x/t_3205x.ori | Bin 0 -> 866 bytes tests/t_3206x/asflags | 0 tests/t_3206x/t_3206x.asm | 241 + tests/t_3206x/t_3206x.doc | 5 + tests/t_3206x/t_3206x.ori | Bin 0 -> 744 bytes tests/t_370/asflags | 0 tests/t_370/t_370.asm | 163 + tests/t_370/t_370.doc | 5 + tests/t_370/t_370.ori | Bin 0 -> 317 bytes tests/t_4004/asflags | 0 tests/t_4004/t_4004.asm | 205 + tests/t_4004/t_4004.doc | 5 + tests/t_4004/t_4004.ori | Bin 0 -> 240 bytes tests/t_403/asflags | 0 tests/t_403/t_403.asm | 27 + tests/t_403/t_403.doc | 6 + tests/t_403/t_403.ori | Bin 0 -> 64 bytes tests/t_4500/asflags | 0 tests/t_4500/t_4500.asm | 109 + tests/t_4500/t_4500.doc | 5 + tests/t_4500/t_4500.ori | Bin 0 -> 246 bytes tests/t_47c00/asflags | 0 tests/t_47c00/t_47c00.asm | 255 + tests/t_47c00/t_47c00.doc | 5 + tests/t_47c00/t_47c00.ori | Bin 0 -> 529 bytes tests/t_48/asflags | 0 tests/t_48/t_48.asm | 178 + tests/t_48/t_48.doc | 5 + tests/t_48/t_48.ori | Bin 0 -> 137 bytes tests/t_56000/asflags | 0 tests/t_56000/t_56000.asm | 244 + tests/t_56000/t_56000.doc | 5 + tests/t_56000/t_56000.ori | Bin 0 -> 980 bytes tests/t_56300/asflags | 0 tests/t_56300/t_56300.asm | 1462 +++ tests/t_56300/t_56300.doc | 6 + tests/t_56300/t_56300.ori | Bin 0 -> 6788 bytes tests/t_65/asflags | 0 tests/t_65/t_65.asm | 283 + tests/t_65/t_65.doc | 5 + tests/t_65/t_65.ori | Bin 0 -> 460 bytes tests/t_6502u/asflags | 0 tests/t_6502u/t_6502u.asm | 110 + tests/t_6502u/t_6502u.doc | 7 + tests/t_6502u/t_6502u.ori | Bin 0 -> 207 bytes tests/t_6804/asflags | 0 tests/t_6804/t_6804.asm | 72 + tests/t_6804/t_6804.doc | 5 + tests/t_6804/t_6804.ori | Bin 0 -> 92 bytes tests/t_68040/asflags | 0 tests/t_68040/t_68040.asm | 29 + tests/t_68040/t_68040.doc | 6 + tests/t_68040/t_68040.ori | Bin 0 -> 60 bytes tests/t_6805/asflags | 0 tests/t_6805/t_6805.asm | 244 + tests/t_6805/t_6805.doc | 5 + tests/t_6805/t_6805.ori | Bin 0 -> 405 bytes tests/t_6808/asflags | 0 tests/t_6808/t_6808.asm | 406 + tests/t_6808/t_6808.doc | 6 + tests/t_6808/t_6808.ori | Bin 0 -> 671 bytes tests/t_6812/asflags | 0 tests/t_6812/t_6812.asm | 644 + tests/t_6812/t_6812.doc | 5 + tests/t_6812/t_6812.ori | Bin 0 -> 1104 bytes tests/t_6816/asflags | 0 tests/t_6816/t_6816.asm | 1037 ++ tests/t_6816/t_6816.doc | 5 + tests/t_6816/t_6816.ori | Bin 0 -> 2874 bytes tests/t_7000/asflags | 0 tests/t_7000/t_7000.asm | 249 + tests/t_7000/t_7000.doc | 5 + tests/t_7000/t_7000.ori | Bin 0 -> 428 bytes tests/t_75k0/asflags | 0 tests/t_75k0/t_75k0.asm | 191 + tests/t_75k0/t_75k0.doc | 5 + tests/t_75k0/t_75k0.ori | Bin 0 -> 262 bytes tests/t_7700/asflags | 0 tests/t_7700/t_7700.asm | 356 + tests/t_7700/t_7700.doc | 5 + tests/t_7700/t_7700.ori | Bin 0 -> 934 bytes tests/t_7720/asflags | 0 tests/t_7720/t_7720.asm | 141 + tests/t_7720/t_7720.doc | 5 + tests/t_7720/t_7720.ori | Bin 0 -> 392 bytes tests/t_77230/asflags | 0 tests/t_77230/t_77230.asm | 245 + tests/t_77230/t_77230.doc | 5 + tests/t_77230/t_77230.ori | Bin 0 -> 668 bytes tests/t_7725/asflags | 0 tests/t_7725/t_7725.asm | 171 + tests/t_7725/t_7725.doc | 5 + tests/t_7725/t_7725.ori | Bin 0 -> 508 bytes tests/t_78c1x/asflags | 0 tests/t_78c1x/t_78c1x.asm | 258 + tests/t_78c1x/t_78c1x.doc | 5 + tests/t_78c1x/t_78c1x.ori | Bin 0 -> 465 bytes tests/t_78k0/asflags | 0 tests/t_78k0/t_78k0.asm | 291 + tests/t_78k0/t_78k0.doc | 5 + tests/t_78k0/t_78k0.ori | Bin 0 -> 606 bytes tests/t_85/asflags | 0 tests/t_85/t_85.asm | 134 + tests/t_85/t_85.doc | 5 + tests/t_85/t_85.ori | Bin 0 -> 180 bytes tests/t_87c800/asflags | 0 tests/t_87c800/t_87c800.asm | 310 + tests/t_87c800/t_87c800.doc | 5 + tests/t_87c800/t_87c800.ori | Bin 0 -> 609 bytes tests/t_8x30x/asflags | 0 tests/t_8x30x/t_8x30x.asm | 57 + tests/t_8x30x/t_8x30x.doc | 5 + tests/t_8x30x/t_8x30x.ori | Bin 0 -> 80 bytes tests/t_96/asflags | 0 tests/t_96/t_96.asm | 217 + tests/t_96/t_96.doc | 5 + tests/t_96/t_96.ori | Bin 0 -> 531 bytes tests/t_960/asflags | 0 tests/t_960/t_960.asm | 101 + tests/t_960/t_960.doc | 5 + tests/t_960/t_960.ori | Bin 0 -> 404 bytes tests/t_97c241/asflags | 0 tests/t_97c241/t_97c241.asm | 336 + tests/t_97c241/t_97c241.doc | 5 + tests/t_97c241/t_97c241.ori | Bin 0 -> 1100 bytes tests/t_9900/asflags | 0 tests/t_9900/t_9900.asm | 222 + tests/t_9900/t_9900.doc | 5 + tests/t_9900/t_9900.ori | Bin 0 -> 550 bytes tests/t_ace/asflags | 0 tests/t_ace/t_ace.asm | 132 + tests/t_ace/t_ace.doc | 5 + tests/t_ace/t_ace.ori | Bin 0 -> 159 bytes tests/t_avr/asflags | 0 tests/t_avr/t_avr.asm | 229 + tests/t_avr/t_avr.doc | 5 + tests/t_avr/t_avr.ori | Bin 0 -> 238 bytes tests/t_bas52/asflags | 0 tests/t_bas52/bas52.clk | 18 + tests/t_bas52/bas52.fp | 1616 +++ tests/t_bas52/bas52.out | 75 + tests/t_bas52/bas52.pgm | 125 + tests/t_bas52/bas52.pwm | 25 + tests/t_bas52/bas52.rst | 111 + tests/t_bas52/bas52.tl | 16 + tests/t_bas52/look52.inc | 779 ++ tests/t_bas52/t_bas52.asm | 4644 ++++++++ tests/t_bas52/t_bas52.doc | 11 + tests/t_bas52/t_bas52.inc | 2 + tests/t_bas52/t_bas52.ori | Bin 0 -> 8192 bytes tests/t_buf32/asflags | 0 tests/t_buf32/t_buf32.asm | 4883 ++++++++ tests/t_buf32/t_buf32.doc | 5 + tests/t_buf32/t_buf32.inc | 2 + tests/t_buf32/t_buf32.ori | Bin 0 -> 8192 bytes tests/t_cop8/asflags | 0 tests/t_cop8/t_cop8.asm | 128 + tests/t_cop8/t_cop8.doc | 5 + tests/t_cop8/t_cop8.ori | Bin 0 -> 262 bytes tests/t_f2mc8l/asflags | 0 tests/t_f2mc8l/t_f2mc8l.asm | 242 + tests/t_f2mc8l/t_f2mc8l.doc | 5 + tests/t_f2mc8l/t_f2mc8l.ori | Bin 0 -> 314 bytes tests/t_fl90/asflags | 0 tests/t_fl90/cpu_time.inc | 170 + tests/t_fl90/float.inc | 1601 +++ tests/t_fl90/macros.inc | 57 + tests/t_fl90/mon.inc | 11 + tests/t_fl90/t_fl90.asm | 179 + tests/t_fl90/t_fl90.doc | 6 + tests/t_fl90/t_fl90.ori | Bin 0 -> 5466 bytes tests/t_fl900/asflags | 0 tests/t_fl900/conout.inc | 154 + tests/t_fl900/cpu_time.inc | 240 + tests/t_fl900/float.inc | 973 ++ tests/t_fl900/macros.inc | 16 + tests/t_fl900/t_fl900.asm | 166 + tests/t_fl900/t_fl900.doc | 6 + tests/t_fl900/t_fl900.inc | 2 + tests/t_fl900/t_fl900.ori | Bin 0 -> 3408 bytes tests/t_full09/asflags | 1 + tests/t_full09/t_full09.asm | 1604 +++ tests/t_full09/t_full09.doc | 6 + tests/t_full09/t_full09.ori | Bin 0 -> 7308 bytes tests/t_h8_3/asflags | 0 tests/t_h8_3/t_h8_3.asm | 353 + tests/t_h8_3/t_h8_3.doc | 5 + tests/t_h8_3/t_h8_3.ori | Bin 0 -> 1156 bytes tests/t_h8_5/asflags | 0 tests/t_h8_5/t_h8_5.asm | 229 + tests/t_h8_5/t_h8_5.doc | 5 + tests/t_h8_5/t_h8_5.ori | Bin 0 -> 407 bytes tests/t_m16c/asflags | 0 tests/t_m16c/t_m16c.asm | 4051 +++++++ tests/t_m16c/t_m16c.doc | 6 + tests/t_m16c/t_m16c.ori | Bin 0 -> 15722 bytes tests/t_mcore/asflags | 0 tests/t_mcore/t_mcore.asm | 140 + tests/t_mcore/t_mcore.doc | 5 + tests/t_mcore/t_mcore.ori | Bin 0 -> 240 bytes tests/t_mic51/DEBUG.ASM | 532 + tests/t_mic51/MAKRO1.ASM | 542 + tests/t_mic51/MEM1.ASM | 727 ++ tests/t_mic51/RUN1.ASM | 773 ++ tests/t_mic51/TAST1.ASM | 250 + tests/t_mic51/TEACH1.ASM | 504 + tests/t_mic51/asflags | 1 + tests/t_mic51/defKey.inc | 83 + tests/t_mic51/defModul.inc | 18 + tests/t_mic51/defMsg.inc | 141 + tests/t_mic51/defParam.inc | 46 + tests/t_mic51/defgequ.inc | 48 + tests/t_mic51/defint.inc | 234 + tests/t_mic51/defmacro.inc | 175 + tests/t_mic51/net_lcd.inc | 33 + tests/t_mic51/t_mic51.asm | 2197 ++++ tests/t_mic51/t_mic51.doc | 6 + tests/t_mic51/t_mic51.inc | 165 + tests/t_mic51/t_mic51.ori | Bin 0 -> 17582 bytes tests/t_mic51/t_mod1.asm | 487 + tests/t_msp/asflags | 0 tests/t_msp/t_msp.asm | 116 + tests/t_msp/t_msp.doc | 5 + tests/t_msp/t_msp.ori | Bin 0 -> 363 bytes tests/t_parsys/asflags | 1 + tests/t_parsys/float.i68 | 1226 ++ tests/t_parsys/float81.i68 | 293 + tests/t_parsys/parsys.i68 | 115 + tests/t_parsys/t_parsys.asm | 994 ++ tests/t_parsys/t_parsys.doc | 8 + tests/t_parsys/t_parsys.inc | 10 + tests/t_parsys/t_parsys.ori | Bin 0 -> 7516 bytes tests/t_scmp/asflags | 0 tests/t_scmp/t_scmp.asm | 59 + tests/t_scmp/t_scmp.doc | 5 + tests/t_scmp/t_scmp.ori | Bin 0 -> 68 bytes tests/t_secdrive/asflags | 0 tests/t_secdrive/lowlevel.inc | 1 + tests/t_secdrive/secparam.inc | 1619 +++ tests/t_secdrive/t_secdrive.asm | 1476 +++ tests/t_secdrive/t_secdrive.doc | 9 + tests/t_secdrive/t_secdrive.ori | Bin 0 -> 11271 bytes tests/t_secdrive/wd1002xt.inc | 773 ++ tests/t_secdrive/wd1003at.inc | 952 ++ tests/t_st6/asflags | 0 tests/t_st6/t_st6.asm | 82 + tests/t_st6/t_st6.doc | 5 + tests/t_st6/t_st6.ori | Bin 0 -> 102 bytes tests/t_st7/asflags | 0 tests/t_st7/t_st7.asm | 561 + tests/t_st7/t_st7.doc | 5 + tests/t_st7/t_st7.ori | Bin 0 -> 1313 bytes tests/t_st9/asflags | 0 tests/t_st9/t_st9.asm | 1243 ++ tests/t_st9/t_st9.doc | 5 + tests/t_st9/t_st9.ori | Bin 0 -> 3290 bytes tests/t_tms7/asflags | 0 tests/t_tms7/t_tms7.asm | 364 + tests/t_tms7/t_tms7.doc | 5 + tests/t_tms7/t_tms7.ori | Bin 0 -> 696 bytes tests/t_xa/asflags | 0 tests/t_xa/t_xa.asm | 603 + tests/t_xa/t_xa.doc | 5 + tests/t_xa/t_xa.ori | Bin 0 -> 1525 bytes tests/t_z380/asflags | 0 tests/t_z380/t_z380.asm | 677 ++ tests/t_z380/t_z380.doc | 5 + tests/t_z380/t_z380.ori | Bin 0 -> 1650 bytes tests/t_z8/asflags | 0 tests/t_z8/t_z8.asm | 116 + tests/t_z8/t_z8.doc | 5 + tests/t_z8/t_z8.ori | Bin 0 -> 180 bytes tests/testall | 38 + tests/testall.bat | 117 + tests/testall.cmd | 117 + tests/warnlog.DE | 35 + tests/warnlog.EN | 35 + tex2doc.c | 2247 ++++ tex2html.c | 2570 ++++ tools.res | 35 + tools2.res | 70 + toolutils.c | 293 + toolutils.h | 52 + tsc.h | 3 + umlaut.c | 65 + unumlaut.c | 91 + ushyph.c | 696 ++ ushyph.h | 14 + version.c | 28 + version.h | 12 + 652 files changed, 204311 insertions(+) create mode 100644 .gitignore create mode 100644 BENCHES create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 Makefile.def-samples/MakeDef.cad create mode 100644 Makefile.def-samples/MakeDef.dos create mode 100644 Makefile.def-samples/MakeDef.dpmi create mode 100644 Makefile.def-samples/Makefile.def-alpha-dec-osf13.2 create mode 100644 Makefile.def-samples/Makefile.def-alpha-dec-osf14.0 create mode 100644 Makefile.def-samples/Makefile.def-alpha-unknown-linux2.x.x create mode 100644 Makefile.def-samples/Makefile.def-hppa-hp-hpux-10.0 create mode 100644 Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.0 create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-dpmi create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-linux2.x.x create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-msdos create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-os2 create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-os2-visualage create mode 100644 Makefile.def-samples/Makefile.def-i386-unknown-win32 create mode 100644 Makefile.def-samples/Makefile.def-m68k-pcs-munix3 create mode 100644 Makefile.def-samples/Makefile.def-m68k-sun-netbsd1.2 create mode 100644 Makefile.def-samples/Makefile.def-mips-dec-netbsd1.2 create mode 100644 Makefile.def-samples/Makefile.def-mips-dec-ultrix4.3 create mode 100644 Makefile.def-samples/Makefile.def-mips-sgi-irix6.2 create mode 100644 Makefile.def-samples/Makefile.def-mips64-sgi-irix6.4 create mode 100644 Makefile.def-samples/Makefile.def-rs6k-ibm-aix41 create mode 100644 Makefile.def-samples/Makefile.def-sparc-sun-solaris2.x create mode 100644 Makefile.def-samples/Makefile.def-sparc-sun-sunos4.1.3 create mode 100644 Makefile.def-samples/Makefile.def-vax-dec-ultrix4.1 create mode 100644 Makefile.def.tmpl create mode 100755 Makefile.dos create mode 100644 Makefile.os2 create mode 100644 README create mode 100644 README.DOS create mode 100644 README.KR create mode 100644 README.LANGS create mode 100644 README.OS2 create mode 100644 TODO create mode 100644 a2k.c create mode 100644 addcr.c create mode 100644 as.c create mode 100644 as.h create mode 100644 as.res create mode 100644 as1750.c create mode 100644 as1750.h create mode 100644 asl.1 create mode 100644 asl.def create mode 100644 asmallg.c create mode 100644 asmallg.h create mode 100644 asmcode.c create mode 100644 asmcode.h create mode 100644 asmdebug.c create mode 100644 asmdebug.h create mode 100644 asmdef.c create mode 100644 asmdef.h create mode 100644 asmfnums.c create mode 100644 asmfnums.h create mode 100644 asmif.c create mode 100644 asmif.h create mode 100644 asminclist.c create mode 100644 asminclist.h create mode 100644 asmitree.c create mode 100644 asmitree.h create mode 100644 asmmac.c create mode 100644 asmmac.h create mode 100644 asmpars.c create mode 100644 asmpars.h create mode 100644 asmrelocs.c create mode 100644 asmrelocs.h create mode 100644 asmsub.c create mode 100644 asmsub.h create mode 100644 bincmp.c create mode 100644 bpemu.c create mode 100644 bpemu.h create mode 100644 changelog create mode 100644 chardefs.h create mode 100644 chunks.c create mode 100644 chunks.h create mode 100644 cmdarg.c create mode 100644 cmdarg.h create mode 100644 cmdarg.res create mode 100644 code166.c create mode 100644 code166.h create mode 100644 code16c5x.c create mode 100644 code16c5x.h create mode 100644 code16c8x.c create mode 100644 code16c8x.h create mode 100644 code17c4x.c create mode 100644 code17c4x.h create mode 100644 code29k.c create mode 100644 code29k.h create mode 100644 code3201x.c create mode 100644 code3201x.h create mode 100644 code3202x.c create mode 100644 code3202x.h create mode 100644 code3203x.c create mode 100644 code3203x.h create mode 100644 code3205x.c create mode 100644 code3205x.h create mode 100644 code3206x.c create mode 100644 code3206x.h create mode 100644 code370.c create mode 100644 code370.h create mode 100644 code4004.c create mode 100644 code4004.h create mode 100644 code4500.c create mode 100644 code4500.h create mode 100644 code47c00.c create mode 100644 code47c00.h create mode 100644 code48.c create mode 100644 code48.h create mode 100644 code51.c create mode 100644 code51.h create mode 100644 code53c8xx.c create mode 100644 code53c8xx.h create mode 100644 code56k.c create mode 100644 code56k.h create mode 100644 code601.c create mode 100644 code601.h create mode 100644 code65.c create mode 100644 code65.h create mode 100644 code68.c create mode 100644 code68.h create mode 100644 code6804.c create mode 100644 code6804.h create mode 100644 code6805.c create mode 100644 code6805.h create mode 100644 code6809.c create mode 100644 code6809.h create mode 100644 code6812.c create mode 100644 code6812.h create mode 100644 code6816.c create mode 100644 code6816.h create mode 100644 code68k.c create mode 100644 code68k.h create mode 100644 code7000.c create mode 100644 code7000.h create mode 100644 code75k0.c create mode 100644 code75k0.h create mode 100644 code7700.c create mode 100644 code7700.h create mode 100644 code7720.c create mode 100644 code7720.h create mode 100644 code77230.c create mode 100644 code77230.h create mode 100644 code78c10.c create mode 100644 code78c10.h create mode 100644 code78k0.c create mode 100644 code78k0.h create mode 100644 code8008.c create mode 100644 code8008.h create mode 100644 code85.c create mode 100644 code85.h create mode 100644 code86.c create mode 100644 code86.h create mode 100644 code87c800.c create mode 100644 code87c800.h create mode 100644 code8x30x.c create mode 100644 code8x30x.h create mode 100644 code90c141.c create mode 100644 code90c141.h create mode 100644 code96.c create mode 100644 code96.h create mode 100644 code960.c create mode 100644 code960.h create mode 100644 code96c141.c create mode 100644 code96c141.h create mode 100644 code97c241.c create mode 100644 code97c241.h create mode 100644 code9900.c create mode 100644 code9900.h create mode 100644 codeace.c create mode 100644 codeace.h create mode 100644 codeavr.c create mode 100644 codeavr.h create mode 100644 codecop8.c create mode 100644 codecop8.h create mode 100644 codeflt1750.c create mode 100644 codeflt1750.h create mode 100644 codefmc8.c create mode 100644 codefmc8.h create mode 100644 codeh8_3.c create mode 100644 codeh8_3.h create mode 100644 codeh8_5.c create mode 100644 codeh8_5.h create mode 100644 codem16.c create mode 100644 codem16.h create mode 100644 codem16c.c create mode 100644 codem16c.h create mode 100644 codemcore.c create mode 100644 codemcore.h create mode 100644 codemsp.c create mode 100644 codemsp.h create mode 100644 codepseudo.c create mode 100644 codepseudo.h create mode 100644 codesc14xxx.c create mode 100644 codesc14xxx.h create mode 100644 codescmp.c create mode 100644 codescmp.h create mode 100644 codest6.c create mode 100644 codest6.h create mode 100644 codest7.c create mode 100644 codest7.h create mode 100644 codest9.c create mode 100644 codest9.h create mode 100644 codetms7.c create mode 100644 codetms7.h create mode 100644 codevars.c create mode 100644 codevars.h create mode 100644 codexa.c create mode 100644 codexa.h create mode 100644 codez8.c create mode 100644 codez8.h create mode 100644 codez80.c create mode 100644 codez80.h create mode 100644 datatypes.h create mode 100644 doc_DE/Makefile create mode 100644 doc_DE/as.tex create mode 100644 doc_DE/dina4.sty create mode 100644 doc_DE/pscomm.tex create mode 100644 doc_DE/pscpu.tex create mode 100644 doc_DE/tabids.tex create mode 100644 doc_DE/taborg1.tex create mode 100644 doc_DE/taborg2.tex create mode 100644 doc_DE/taborg3.tex create mode 100644 doc_DE/taborg4.tex create mode 100644 doc_EN/Makefile create mode 100644 doc_EN/as.tex create mode 100644 endian.c create mode 100644 endian.h create mode 100644 equs.h create mode 100644 fileformat.h create mode 100644 findhyphen.c create mode 100644 findhyphen.h create mode 100644 grhyph.c create mode 100644 grhyph.h create mode 100644 header.res create mode 100644 headids.c create mode 100644 headids.h create mode 100644 hex.c create mode 100644 hex.h create mode 100644 include/80c50x.inc create mode 100644 include/80c552.inc create mode 100644 include/bitfuncs.inc create mode 100644 include/ctype.inc create mode 100644 include/h8_3048.inc create mode 100644 include/reg166.inc create mode 100644 include/reg251.inc create mode 100644 include/reg29k.inc create mode 100644 include/reg53x.inc create mode 100644 include/reg683xx.inc create mode 100644 include/reg7000.inc create mode 100644 include/reg78k0.inc create mode 100644 include/reg96.inc create mode 100644 include/regavr.inc create mode 100644 include/regcop8.inc create mode 100644 include/reghc12.inc create mode 100644 include/regm16c.inc create mode 100644 include/regmsp.inc create mode 100644 include/regst9.inc create mode 100644 include/regz380.inc create mode 100644 include/stddef04.inc create mode 100644 include/stddef16.inc create mode 100644 include/stddef17.inc create mode 100644 include/stddef18.inc create mode 100644 include/stddef2x.inc create mode 100644 include/stddef37.inc create mode 100644 include/stddef3x.inc create mode 100644 include/stddef47.inc create mode 100644 include/stddef51.inc create mode 100644 include/stddef56k.inc create mode 100644 include/stddef5x.inc create mode 100644 include/stddef60.inc create mode 100644 include/stddef62.inc create mode 100644 include/stddef75.inc create mode 100644 include/stddef87.inc create mode 100644 include/stddef90.inc create mode 100644 include/stddef96.inc create mode 100644 include/stddefxa.inc create mode 100644 include/stddefz8.inc create mode 100644 install.bat create mode 100644 install.cmd create mode 100755 install.sh create mode 100644 ioerrs.c create mode 100644 ioerrs.h create mode 100644 ioerrs.res create mode 100644 makedefs.files create mode 100644 makedefs.src create mode 100644 makedefs.str create mode 100644 marks.asm create mode 100644 nlmessages.c create mode 100644 nlmessages.h create mode 100644 nls.c create mode 100644 nls.h create mode 100644 objdefs.dos create mode 100644 objdefs.unix create mode 100644 p2bin.1 create mode 100644 p2bin.c create mode 100644 p2bin.res create mode 100644 p2hex.1 create mode 100644 p2hex.c create mode 100644 p2hex.res create mode 100644 pascstyle.h create mode 100644 pbind.1 create mode 100644 pbind.c create mode 100644 pbind.res create mode 100644 plist.1 create mode 100644 plist.c create mode 100644 plist.res create mode 100644 reltypes.c create mode 100644 rescomp.c create mode 100644 specchars.h create mode 100644 stdhandl.c create mode 100644 stdhandl.h create mode 100644 stdinc.h create mode 100644 stringlists.c create mode 100644 stringlists.h create mode 100644 strutil.c create mode 100644 strutil.h create mode 100644 sysdefs.h create mode 100644 tests/t_166/asflags create mode 100644 tests/t_166/t_166.asm create mode 100644 tests/t_166/t_166.doc create mode 100644 tests/t_166/t_166.ori create mode 100644 tests/t_16c5x/asflags create mode 100755 tests/t_16c5x/t_16c5x.asm create mode 100644 tests/t_16c5x/t_16c5x.doc create mode 100755 tests/t_16c5x/t_16c5x.ori create mode 100644 tests/t_16c84/asflags create mode 100644 tests/t_16c84/t_16c84.asm create mode 100644 tests/t_16c84/t_16c84.doc create mode 100644 tests/t_16c84/t_16c84.ori create mode 100644 tests/t_17c42/asflags create mode 100644 tests/t_17c42/t_17c42.asm create mode 100644 tests/t_17c42/t_17c42.doc create mode 100644 tests/t_17c42/t_17c42.ori create mode 100644 tests/t_251/asflags create mode 100644 tests/t_251/t_251.asm create mode 100644 tests/t_251/t_251.doc create mode 100644 tests/t_251/t_251.ori create mode 100644 tests/t_296/asflags create mode 100644 tests/t_296/t_296.asm create mode 100644 tests/t_296/t_296.doc create mode 100755 tests/t_296/t_296.ori create mode 100644 tests/t_29k/asflags create mode 100644 tests/t_29k/t_29k.asm create mode 100644 tests/t_29k/t_29k.doc create mode 100644 tests/t_29k/t_29k.ori create mode 100644 tests/t_32/asflags create mode 100644 tests/t_32/t_32.asm create mode 100644 tests/t_32/t_32.doc create mode 100644 tests/t_32/t_32.ori create mode 100644 tests/t_3201x/asflags create mode 100644 tests/t_3201x/t_3201x.asm create mode 100644 tests/t_3201x/t_3201x.doc create mode 100644 tests/t_3201x/t_3201x.ori create mode 100644 tests/t_3203x/asflags create mode 100644 tests/t_3203x/t_3203x.asm create mode 100644 tests/t_3203x/t_3203x.doc create mode 100755 tests/t_3203x/t_3203x.ori create mode 100644 tests/t_3205x/asflags create mode 100644 tests/t_3205x/t_3205x.asm create mode 100644 tests/t_3205x/t_3205x.doc create mode 100644 tests/t_3205x/t_3205x.ori create mode 100644 tests/t_3206x/asflags create mode 100644 tests/t_3206x/t_3206x.asm create mode 100644 tests/t_3206x/t_3206x.doc create mode 100644 tests/t_3206x/t_3206x.ori create mode 100644 tests/t_370/asflags create mode 100644 tests/t_370/t_370.asm create mode 100644 tests/t_370/t_370.doc create mode 100644 tests/t_370/t_370.ori create mode 100644 tests/t_4004/asflags create mode 100644 tests/t_4004/t_4004.asm create mode 100644 tests/t_4004/t_4004.doc create mode 100644 tests/t_4004/t_4004.ori create mode 100644 tests/t_403/asflags create mode 100644 tests/t_403/t_403.asm create mode 100644 tests/t_403/t_403.doc create mode 100644 tests/t_403/t_403.ori create mode 100644 tests/t_4500/asflags create mode 100644 tests/t_4500/t_4500.asm create mode 100644 tests/t_4500/t_4500.doc create mode 100644 tests/t_4500/t_4500.ori create mode 100644 tests/t_47c00/asflags create mode 100644 tests/t_47c00/t_47c00.asm create mode 100644 tests/t_47c00/t_47c00.doc create mode 100644 tests/t_47c00/t_47c00.ori create mode 100644 tests/t_48/asflags create mode 100644 tests/t_48/t_48.asm create mode 100644 tests/t_48/t_48.doc create mode 100644 tests/t_48/t_48.ori create mode 100644 tests/t_56000/asflags create mode 100644 tests/t_56000/t_56000.asm create mode 100644 tests/t_56000/t_56000.doc create mode 100644 tests/t_56000/t_56000.ori create mode 100644 tests/t_56300/asflags create mode 100644 tests/t_56300/t_56300.asm create mode 100644 tests/t_56300/t_56300.doc create mode 100644 tests/t_56300/t_56300.ori create mode 100644 tests/t_65/asflags create mode 100755 tests/t_65/t_65.asm create mode 100644 tests/t_65/t_65.doc create mode 100755 tests/t_65/t_65.ori create mode 100644 tests/t_6502u/asflags create mode 100644 tests/t_6502u/t_6502u.asm create mode 100644 tests/t_6502u/t_6502u.doc create mode 100644 tests/t_6502u/t_6502u.ori create mode 100644 tests/t_6804/asflags create mode 100644 tests/t_6804/t_6804.asm create mode 100644 tests/t_6804/t_6804.doc create mode 100644 tests/t_6804/t_6804.ori create mode 100644 tests/t_68040/asflags create mode 100644 tests/t_68040/t_68040.asm create mode 100644 tests/t_68040/t_68040.doc create mode 100644 tests/t_68040/t_68040.ori create mode 100644 tests/t_6805/asflags create mode 100755 tests/t_6805/t_6805.asm create mode 100644 tests/t_6805/t_6805.doc create mode 100755 tests/t_6805/t_6805.ori create mode 100644 tests/t_6808/asflags create mode 100644 tests/t_6808/t_6808.asm create mode 100644 tests/t_6808/t_6808.doc create mode 100644 tests/t_6808/t_6808.ori create mode 100644 tests/t_6812/asflags create mode 100644 tests/t_6812/t_6812.asm create mode 100644 tests/t_6812/t_6812.doc create mode 100644 tests/t_6812/t_6812.ori create mode 100644 tests/t_6816/asflags create mode 100644 tests/t_6816/t_6816.asm create mode 100644 tests/t_6816/t_6816.doc create mode 100644 tests/t_6816/t_6816.ori create mode 100644 tests/t_7000/asflags create mode 100644 tests/t_7000/t_7000.asm create mode 100644 tests/t_7000/t_7000.doc create mode 100644 tests/t_7000/t_7000.ori create mode 100644 tests/t_75k0/asflags create mode 100644 tests/t_75k0/t_75k0.asm create mode 100644 tests/t_75k0/t_75k0.doc create mode 100644 tests/t_75k0/t_75k0.ori create mode 100644 tests/t_7700/asflags create mode 100644 tests/t_7700/t_7700.asm create mode 100644 tests/t_7700/t_7700.doc create mode 100644 tests/t_7700/t_7700.ori create mode 100644 tests/t_7720/asflags create mode 100644 tests/t_7720/t_7720.asm create mode 100644 tests/t_7720/t_7720.doc create mode 100644 tests/t_7720/t_7720.ori create mode 100644 tests/t_77230/asflags create mode 100644 tests/t_77230/t_77230.asm create mode 100644 tests/t_77230/t_77230.doc create mode 100644 tests/t_77230/t_77230.ori create mode 100644 tests/t_7725/asflags create mode 100644 tests/t_7725/t_7725.asm create mode 100644 tests/t_7725/t_7725.doc create mode 100644 tests/t_7725/t_7725.ori create mode 100644 tests/t_78c1x/asflags create mode 100644 tests/t_78c1x/t_78c1x.asm create mode 100644 tests/t_78c1x/t_78c1x.doc create mode 100644 tests/t_78c1x/t_78c1x.ori create mode 100644 tests/t_78k0/asflags create mode 100644 tests/t_78k0/t_78k0.asm create mode 100644 tests/t_78k0/t_78k0.doc create mode 100644 tests/t_78k0/t_78k0.ori create mode 100644 tests/t_85/asflags create mode 100644 tests/t_85/t_85.asm create mode 100644 tests/t_85/t_85.doc create mode 100644 tests/t_85/t_85.ori create mode 100644 tests/t_87c800/asflags create mode 100644 tests/t_87c800/t_87c800.asm create mode 100644 tests/t_87c800/t_87c800.doc create mode 100644 tests/t_87c800/t_87c800.ori create mode 100644 tests/t_8x30x/asflags create mode 100644 tests/t_8x30x/t_8x30x.asm create mode 100644 tests/t_8x30x/t_8x30x.doc create mode 100644 tests/t_8x30x/t_8x30x.ori create mode 100644 tests/t_96/asflags create mode 100644 tests/t_96/t_96.asm create mode 100644 tests/t_96/t_96.doc create mode 100644 tests/t_96/t_96.ori create mode 100644 tests/t_960/asflags create mode 100644 tests/t_960/t_960.asm create mode 100644 tests/t_960/t_960.doc create mode 100644 tests/t_960/t_960.ori create mode 100644 tests/t_97c241/asflags create mode 100644 tests/t_97c241/t_97c241.asm create mode 100644 tests/t_97c241/t_97c241.doc create mode 100644 tests/t_97c241/t_97c241.ori create mode 100644 tests/t_9900/asflags create mode 100644 tests/t_9900/t_9900.asm create mode 100644 tests/t_9900/t_9900.doc create mode 100644 tests/t_9900/t_9900.ori create mode 100644 tests/t_ace/asflags create mode 100644 tests/t_ace/t_ace.asm create mode 100644 tests/t_ace/t_ace.doc create mode 100644 tests/t_ace/t_ace.ori create mode 100644 tests/t_avr/asflags create mode 100644 tests/t_avr/t_avr.asm create mode 100644 tests/t_avr/t_avr.doc create mode 100644 tests/t_avr/t_avr.ori create mode 100644 tests/t_bas52/asflags create mode 100644 tests/t_bas52/bas52.clk create mode 100644 tests/t_bas52/bas52.fp create mode 100644 tests/t_bas52/bas52.out create mode 100644 tests/t_bas52/bas52.pgm create mode 100644 tests/t_bas52/bas52.pwm create mode 100644 tests/t_bas52/bas52.rst create mode 100644 tests/t_bas52/bas52.tl create mode 100644 tests/t_bas52/look52.inc create mode 100644 tests/t_bas52/t_bas52.asm create mode 100644 tests/t_bas52/t_bas52.doc create mode 100644 tests/t_bas52/t_bas52.inc create mode 100644 tests/t_bas52/t_bas52.ori create mode 100644 tests/t_buf32/asflags create mode 100644 tests/t_buf32/t_buf32.asm create mode 100644 tests/t_buf32/t_buf32.doc create mode 100644 tests/t_buf32/t_buf32.inc create mode 100644 tests/t_buf32/t_buf32.ori create mode 100644 tests/t_cop8/asflags create mode 100644 tests/t_cop8/t_cop8.asm create mode 100644 tests/t_cop8/t_cop8.doc create mode 100644 tests/t_cop8/t_cop8.ori create mode 100644 tests/t_f2mc8l/asflags create mode 100644 tests/t_f2mc8l/t_f2mc8l.asm create mode 100644 tests/t_f2mc8l/t_f2mc8l.doc create mode 100644 tests/t_f2mc8l/t_f2mc8l.ori create mode 100644 tests/t_fl90/asflags create mode 100644 tests/t_fl90/cpu_time.inc create mode 100644 tests/t_fl90/float.inc create mode 100644 tests/t_fl90/macros.inc create mode 100644 tests/t_fl90/mon.inc create mode 100644 tests/t_fl90/t_fl90.asm create mode 100644 tests/t_fl90/t_fl90.doc create mode 100644 tests/t_fl90/t_fl90.ori create mode 100644 tests/t_fl900/asflags create mode 100644 tests/t_fl900/conout.inc create mode 100644 tests/t_fl900/cpu_time.inc create mode 100644 tests/t_fl900/float.inc create mode 100644 tests/t_fl900/macros.inc create mode 100644 tests/t_fl900/t_fl900.asm create mode 100644 tests/t_fl900/t_fl900.doc create mode 100644 tests/t_fl900/t_fl900.inc create mode 100755 tests/t_fl900/t_fl900.ori create mode 100644 tests/t_full09/asflags create mode 100644 tests/t_full09/t_full09.asm create mode 100644 tests/t_full09/t_full09.doc create mode 100644 tests/t_full09/t_full09.ori create mode 100644 tests/t_h8_3/asflags create mode 100644 tests/t_h8_3/t_h8_3.asm create mode 100644 tests/t_h8_3/t_h8_3.doc create mode 100644 tests/t_h8_3/t_h8_3.ori create mode 100644 tests/t_h8_5/asflags create mode 100644 tests/t_h8_5/t_h8_5.asm create mode 100644 tests/t_h8_5/t_h8_5.doc create mode 100644 tests/t_h8_5/t_h8_5.ori create mode 100644 tests/t_m16c/asflags create mode 100644 tests/t_m16c/t_m16c.asm create mode 100644 tests/t_m16c/t_m16c.doc create mode 100644 tests/t_m16c/t_m16c.ori create mode 100644 tests/t_mcore/asflags create mode 100644 tests/t_mcore/t_mcore.asm create mode 100644 tests/t_mcore/t_mcore.doc create mode 100644 tests/t_mcore/t_mcore.ori create mode 100644 tests/t_mic51/DEBUG.ASM create mode 100644 tests/t_mic51/MAKRO1.ASM create mode 100644 tests/t_mic51/MEM1.ASM create mode 100644 tests/t_mic51/RUN1.ASM create mode 100644 tests/t_mic51/TAST1.ASM create mode 100644 tests/t_mic51/TEACH1.ASM create mode 100644 tests/t_mic51/asflags create mode 100644 tests/t_mic51/defKey.inc create mode 100644 tests/t_mic51/defModul.inc create mode 100644 tests/t_mic51/defMsg.inc create mode 100644 tests/t_mic51/defParam.inc create mode 100644 tests/t_mic51/defgequ.inc create mode 100644 tests/t_mic51/defint.inc create mode 100644 tests/t_mic51/defmacro.inc create mode 100644 tests/t_mic51/net_lcd.inc create mode 100644 tests/t_mic51/t_mic51.asm create mode 100644 tests/t_mic51/t_mic51.doc create mode 100644 tests/t_mic51/t_mic51.inc create mode 100755 tests/t_mic51/t_mic51.ori create mode 100644 tests/t_mic51/t_mod1.asm create mode 100644 tests/t_msp/asflags create mode 100644 tests/t_msp/t_msp.asm create mode 100644 tests/t_msp/t_msp.doc create mode 100644 tests/t_msp/t_msp.ori create mode 100644 tests/t_parsys/asflags create mode 100644 tests/t_parsys/float.i68 create mode 100644 tests/t_parsys/float81.i68 create mode 100644 tests/t_parsys/parsys.i68 create mode 100644 tests/t_parsys/t_parsys.asm create mode 100644 tests/t_parsys/t_parsys.doc create mode 100644 tests/t_parsys/t_parsys.inc create mode 100644 tests/t_parsys/t_parsys.ori create mode 100644 tests/t_scmp/asflags create mode 100644 tests/t_scmp/t_scmp.asm create mode 100644 tests/t_scmp/t_scmp.doc create mode 100755 tests/t_scmp/t_scmp.ori create mode 100644 tests/t_secdrive/asflags create mode 120000 tests/t_secdrive/lowlevel.inc create mode 100644 tests/t_secdrive/secparam.inc create mode 100644 tests/t_secdrive/t_secdrive.asm create mode 100644 tests/t_secdrive/t_secdrive.doc create mode 100755 tests/t_secdrive/t_secdrive.ori create mode 100644 tests/t_secdrive/wd1002xt.inc create mode 100644 tests/t_secdrive/wd1003at.inc create mode 100644 tests/t_st6/asflags create mode 100755 tests/t_st6/t_st6.asm create mode 100644 tests/t_st6/t_st6.doc create mode 100755 tests/t_st6/t_st6.ori create mode 100644 tests/t_st7/asflags create mode 100644 tests/t_st7/t_st7.asm create mode 100644 tests/t_st7/t_st7.doc create mode 100644 tests/t_st7/t_st7.ori create mode 100644 tests/t_st9/asflags create mode 100644 tests/t_st9/t_st9.asm create mode 100644 tests/t_st9/t_st9.doc create mode 100755 tests/t_st9/t_st9.ori create mode 100644 tests/t_tms7/asflags create mode 100755 tests/t_tms7/t_tms7.asm create mode 100644 tests/t_tms7/t_tms7.doc create mode 100755 tests/t_tms7/t_tms7.ori create mode 100644 tests/t_xa/asflags create mode 100644 tests/t_xa/t_xa.asm create mode 100644 tests/t_xa/t_xa.doc create mode 100644 tests/t_xa/t_xa.ori create mode 100644 tests/t_z380/asflags create mode 100644 tests/t_z380/t_z380.asm create mode 100644 tests/t_z380/t_z380.doc create mode 100644 tests/t_z380/t_z380.ori create mode 100644 tests/t_z8/asflags create mode 100644 tests/t_z8/t_z8.asm create mode 100644 tests/t_z8/t_z8.doc create mode 100644 tests/t_z8/t_z8.ori create mode 100755 tests/testall create mode 100644 tests/testall.bat create mode 100644 tests/testall.cmd create mode 100644 tests/warnlog.DE create mode 100644 tests/warnlog.EN create mode 100644 tex2doc.c create mode 100644 tex2html.c create mode 100644 tools.res create mode 100644 tools2.res create mode 100644 toolutils.c create mode 100644 toolutils.h create mode 100644 tsc.h create mode 100644 umlaut.c create mode 100644 unumlaut.c create mode 100644 ushyph.c create mode 100644 ushyph.h create mode 100644 version.c create mode 100644 version.h 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. +-----------------------------------------------------------------------------------------------------------------------------+------------------------------------------- + 2*Pentium2 450 Linux gcc | 0.28s 0.14s 1.62s 231.31 0.514 + 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] + 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] + Natoma Chipset PPro 233 [16K+16K]/256K 64 Linux 2.1.42 pent-gcc | 0.82s 0.45s 4.53s 77.76 0.334 + 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] + 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] + 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] + 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] + 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] + 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. +-----------------------------------------------------------------------------------------------------------------------------+------------------------------------------- + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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 + 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] + 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] + 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] + 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] + 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] + 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 + 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 + 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] + 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 + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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 + 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] + 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 + 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] + 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 + 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] + 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] + 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 + 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 + 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] + 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] + 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 + 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] + No Chipset i486DX2 50 [8K] 16 Linux 2.0.27 gcc 2.7.2 | 11.53s 5.41s 66.61s 5.75 0.115 + 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 + 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] + 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 + 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] + 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 + 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 + 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] + 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 + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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 + 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] + 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 + 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 + 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] + 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] + 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] + 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] + 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] + 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 + 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] + 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 + 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] + 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] + 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] + 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 + 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 + 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 + 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 + 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] + 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 + 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] + 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 + 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 + 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] + 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] + 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 + 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 + 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 + 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 + 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] + 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] + 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] + 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] + 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] + 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 + 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] + 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 + 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] + 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] + 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] + 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 + 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. +-----------------------------------------------------------------------------------------------------------------------------+------------------------------------------- + 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] + 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] + 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] + 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] + 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] + 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] + 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] + 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. +-----------------------------------------------------------------------------------------------------------------------------+------------------------------------------- + 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] + 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' 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) + +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: + + ä ë ï ö ü + --> lowercase umlauted characters + Ä Ë Ï Ö Ü + --> uppercase umlauted characters + ß + --> german sharp s + ² + --> exponential 2 + µ + --> micron character + à è ì ò ù + --> lowercase accent grave characters + À È Ì Ò Ù + --> uppercase accent grave characters + á é í ó ú + --> lowercase accent acute characters + Á É Í Ó Ú + --> uppercase accent acute characters + â ê î ô û + --> lowercase accent circonflex characters + Â Ê Î Ô Û + --> uppercase accent circonflex characters + ç Ç + --> lowercase / uppercase cedilla + ñ Ñ + --> lowercase / uppercase tilded n + å Å + --> lowercase / uppercase ringed a + æ &Aelig; + --> lowercase / uppercase ae diphtong + ¿ ¡ + --> 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 + 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 +#include +#include +#include + +/*** 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 \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=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 + +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 +#include +#include + +#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 (ni)) + 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 (ArgCntParamCount) + 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>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 (pLength(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; z0) + 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; zParamCount) + 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, überflüssig" + "useless displacement 0" + +Message ErrMsgShortAddrPossible + "Kurzadressierung möglich" + "short addressing possible" + +Message ErrMsgShortJumpPossible + "kurzer Sprung mö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 + "Änderung des Symbolwertes erzwingt zusätzlichen Pass" + "change of symbol values forces additional pass" + +Message ErrMsgOverlap + "überlappende Speicherbelegung" + "overlapping memory usage" + +Message ErrMsgNoCaseHit + "keine CASE-Bedingung zugetroffen" + "none of the CASE conditions was true" + +Message ErrMsgInAccPage + "Seite möglicherweise nicht adressierbar" + "page might not be addressable" + +Message ErrMsgRMustBeEven + "Registernummer muß gerade sein" + "register number must be even" + +Message ErrMsgObsolete + "veralteter Befehl" + "obsolete instruction, usage discouraged" + +Message ErrMsgUnpredictable + "nicht vorhersagbare Ausführung dieser Anweisung" + "unpredictable execution of this instruction" + +Message ErrMsgAlphaNoSense + "Lokaloperator außerhalb einer Sektion überflüssig" + "localization operator senseless out of a section" + +Message ErrMsgSenseless + "sinnlose Operation" + "senseless instruction" + +Message ErrMsgRepassUnknown + "unbekannter Symbolwert erzwingt zusä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ögliche Pipelining-Effekte" + "possible pipelining effects" + +Message ErrMsgDoubleAdrRegUse + "mehrfache Adreß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 überschreitet Seitengrenze" + "instruction crosses page boundary" + +Message ErrMsgWOverRange + "Bereichsüberschreitung" + "range overflow" + +Message ErrMsgNegDUP + "negatives Argument für DUP" + "negative argument for DUP" + +;***** + +Message ErrMsgDoubleDef + "Symbol doppelt definiert" + "symbol double defined" + +Message ErrMsgSymbolUndef + "Symbol nicht definiert" + "symbol undefined" + +Message ErrMsgInvSymName + "ungültiger Symbolname" + "invalid symbol name" + +Message ErrMsgInvFormat + "ungültiges Format" + "invalid format" + +Message ErrMsgUseLessAttr + "überflü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öße" + "invalid operand size" + +Message ErrMsgConfOpSizes + "widersprechende Operandengrößen" + "conflicting operand sizes" + +Message ErrMsgUndefOpSizes + "undefinierte Operandengröß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überschreitung" + "range overflow" + +Message ErrMsgNotAligned + "Adresse nicht ausgerichtet" + "address is not properly aligned" + +Message ErrMsgDistTooBig + "Distanz zu groß" + "distance too big" + +Message ErrMsgInAccReg + "Register nicht zugreifbar" + "register not accessible" + +Message ErrMsgNoShortAddr + "Kurzadressierung nicht möglich" + "short addressing not allowed" + +Message ErrMsgInvAddrMode + "unerlaubter Adressierungsmodus" + "addressing mode not allowed here" + +Message ErrMsgMustBeEven + "Nummer muß 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ß" + "jump distance too big" + +Message ErrMsgDistIsOdd + "Sprungdistanz ist ungerade" + "jump distance is odd" + +Message ErrMsgInvShiftArg + "ungü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ß" + "shift amplitude too big" + +Message ErrMsgInvRegList + "ungültige Registerliste" + "invalid register list" + +Message ErrMsgInvCmpMode + "ungültiger Modus mit CMP" + "invalid addressing mode for CMP" + +Message ErrMsgInvCPUType + "ungültiger Prozessortyp" + "invalid CPU type" + +Message ErrMsgInvCtrlReg + "ungültiges Kontrollregister" + "invalid control register" + +Message ErrMsgInvReg + "ungü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ü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öste Vorwärtsdeklaration" + "unresolved forward declaration" + +Message ErrMsgContForward + "widersprechende FORWARD <-> PUBLIC-Deklaration" + "conflicting FORWARD <-> PUBLIC-declaration" + +Message ErrMsgInvFuncArgCnt + "falsche Argumentzahl für Funktion" + "wrong numbers of function arguments" + +Message ErrMsgMissingLTORG + "unaufgelö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ü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ü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ültiger Funktionscode" + "invalid function code" + +Message ErrMsgInvFMask + "ungültige Funktionscodemaske" + "invalid function code mask" + +Message ErrMsgInvMMUReg + "ungültiges MMU-Register" + "invalid MMU register" + +Message ErrMsgLevel07 + "Level nur von 0..7" + "level must be in range 0..7" + +Message ErrMsgInvBitMask + "ungültige Bitmaske" + "invalid bit mask" + +Message ErrMsgInvRegPair + "ungü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ßerhalb eines Makrorumpfes" + "EXITM not called from within macro" + +Message ErrMsgFirstPassCalc + "Ausdruck muß 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ßerhalb Definitionsbereich" + "function argument out of definition range" + +Message ErrMsgFloatOverflow + "Gleitkommaüberlauf" + "floating point overflow" + +Message ErrMsgInvArgPair + "ungültiges Wertepaar" + "invalid value pair" + +Message ErrMsgNotOnThisAddress + "Befehl darf nicht auf dieser Adresse liegen" + "instruction must not start on this address" + +Message ErrMsgNotFromThisAddress + "ungültiges Sprungziel" + "invalid jump target" + +Message ErrMsgTargOnDiffPage + "Sprungziel nicht auf gleicher Seite" + "jump target not on same page" + +Message ErrMsgCodeOverflow + "Codeüberlauf" + "code overflow" + +Message ErrMsgMixDBDS + "Konstanten und Platzhalter nicht mischbar" + "constants and placeholders cannot be mixed" + +Message ErrMsgNotInStruct + "Codeerzeugung in Strukturdefinition nicht zulässig" + "code must not be generated in structure definition" + +Message ErrMsgParNotPossible + "paralleles Konstrukt nicht möglich" + "parallel construct not possible here" + +Message ErrMsgAdrOverflow + "Adreßüberlauf" + "address overflow" + +Message ErrMsgInvSegment + "ungültiges Segment" + "invalid segment" + +Message ErrMsgUnknownSegment + "unbekanntes Segment" + "unknown segment" + +Message ErrMsgUnknownSegReg + "unbekanntes Segmentregister" + "unknown segment register" + +Message ErrMsgInvString + "ungültiger String" + "invalid string" + +Message ErrMsgInvRegName + "ungültiger Registername" + "invalid register name" + +Message ErrMsgInvArg + "ungü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ässig" + "not allowed in maximum mode" + +Message ErrMsgOnlyInMaxmode + "nicht im Minimum-Modus zulässig" + "not allowed in minimum mode" + +Message ErrMsgOpeningFile + "Fehler beim Ö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überlauf" + "heap overflow" + +Message ErrMsgStackOvfl + "Stapelü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ültige Größenangabe für Swapfile - Programmabbruch" + "swap file size not correctly specified - program terminated" + +Message ErrMsgSwapTooBig + "zuwenig Platz fü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ändertes Zeichen" + " changed character" + +Message ListCodepagePChange + " verä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äufe" + " passes" + +Message InfoMessNoPass + " zusätzliche erforderliche Durchläufe wegen Fehlern nicht\n durchgeführt, Listing mö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ügbarer Restspeicher" + " Kbytes available memory" + +Message InfoMessRemainStack + " Byte verfü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 ---" + "--- to go on ---" + +Message ErrMsgInvParam + "ungültige Option: " + "invalid option: " + +Message ErrMsgInvEnvParam + "ungü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 : Namen der Code-Datei neu setzen\n" \ + "-shareout : Namen des Sharefiles neu setzen\n" \ + "-q, -quiet : Stille Übersetzung\n" \ + "-cpu : Zielprozessor setzen\n" \ + "-alias = : Prozessor-Alias definieren\n" \ + "-l : Listing auf Konsole -L : Listing auf Datei\n" \ + "-i [:Pfad]... : Pfadliste für Includedateien\n" \ + "-D [,Symbol]... : Symbole vordefinieren\n" \ + "-E [Name] : Zieldatei für Fehlerliste,\n" \ + " !0..!4 für Standardhandles\n" \ + " Default .LOG\n" \ + "-r : Meldungen erzeugen, falls zusätzlicher Pass erforderlich\n" \ + "-Y : Sprungfehlerunterdrückung (siehe Anleitung)\n" \ + "-w : Warnungen unterdrücken +G : Code-Erzeugung unterdrü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 : change name of code file\n" \ + "-shareout : change name of share file\n" \ + "-q, -quiet : silent compilation\n" \ + "-cpu : set target processor\n" \ + "-alias = : define processor alias\n" \ + "-l : listing to console -L : listing to file\n" \ + "-i [;path]... : list of paths for include files\n" \ + "-D [,symbol]... : predefine symbols\n" \ + "-E : target file for error list,\n" \ + " !0..!4 for standard handles\n" \ + " default is .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 +#include +#include +#include +#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 +Set the target processor to . Use this option if the source file does +not contain a CPU statement. +.TP +.B -alias +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 [,...] +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 +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 +Tell AS to write the code output to a file . 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 +Tell AS to write shared symbol definitions to a file , 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 +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 , whereas a negated +parameter (+t) resets the bits set in . 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 + + +#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' ' ? 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 ((zNext=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 (RestName,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=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 + +#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=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 + +#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(<urn,4); + if (fwrite(((Byte *) <urn)+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; ActFileContents.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 + +#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 (StartFirstAddr) 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 +#include + +#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 + +#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; zLen; 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; zLen; 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 + +#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; zFill=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; zSize; 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; zSize; 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 +#include + +#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; zCompiled[(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=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 ((p3Next; + 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 +#include + +#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=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; zopId,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.IntContents.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; z1Contents.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.IntContents.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; z1Contents.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<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 (l1SymType]; 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; SpaceLeft!=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; zUsage.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; FileZRefList; + + 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 +#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 +#include + +#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=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; nTyp) + 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) > >"); + 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 (ValueMax) + 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<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='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 + + long GTime(void) +BEGIN + static unsigned long *tick=MK_FP(0x40,0x6c); + double tmp=*tick; + + return ((long) (tmp*5.4931641)); +END + +#elif __IBMC__ + +#include +#define INCL_DOSDATETIME +#include + + 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 + + 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 +#endif + + void ChkStack(void) +BEGIN +#ifdef __TURBOC__ + LongWord avail=stackavail(); + if (avail + +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 \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 +#include +#include +#include + +#include "strutil.h" +#include "bpemu.h" + +#ifdef __MSDOS__ +#include +#include +#endif + +#if defined( __EMX__ ) || defined( __IBMC__ ) +#include +#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 + 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 ,FPm funktionierte mit = 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; zRealLen; 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; zRealLen; 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; zRealLen; z++) + if (NChunk->Chunks[z].StartChunks[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; zRealLen; 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; zRealLen; 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 +#include + +#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; z1) AND (strcmp(s,Def[Search].Ident)==0)) 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 +#include + +#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 (((MPos0xffff) 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> 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=0) + if (--ExtCounter<0) + BEGIN + MemMode=MemModeStd; + ExtSFRs=False; + END + + /* ohne Argument */ + + for (z=0; z> 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; z3) 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; z15) 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=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; z254))) 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> 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 + +#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; z2)) 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; zROMEnd()) 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< + +#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; z2)) 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; zROMEnd()) 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< +#include + +#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; z2MaxCodeLen) 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; z2)) 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 +#include + +#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; z3) 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; z3) 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=-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< +#include + +#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; z2)) 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; z3)) 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; zImmOrders[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< + * + * 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 +#include + +#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 +#include + +#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 ((*ErgDisplacement + -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; z23) *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; z3) 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>=1; + END + if (z3>=1; + END + if (z37) 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> 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; z0x7fffl) 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; z0x7fffl) 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; z15)) 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 + * + * 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 +#include + +#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 +#include + +#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 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> 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; z0) + 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> 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; z14) 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< +#include + +#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 (p127) 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; z127) 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; z127) OR (AdrInt<-128))) + BEGIN + WrError(1370); CodeLen=0; + END + else BAsmCode[CodeLen++]=AdrInt & 0xff; + END + END + return; + END + + for (z=0; z127) OR (AdrInt<-128))) + BEGIN + WrError(1370); CodeLen=0; + END + else BAsmCode[CodeLen++]=AdrInt & 0xff; + END + END + return; + END + + for (z=0; z> 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< +#include + +#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> 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< + +#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> 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> 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< + +#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> 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=4) WrError(160); + END + END + return; + END + + for (z=0; z1) 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< +#include + +#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'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 +#include + +#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<=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> 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 ((MPos1) 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=0) H32 += ((LongWord)SegType) << 16; + if (FirstFlag) + if ((MomCPU0xffff)) 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>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>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) 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 ((MomCPU7) 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=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> 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> 16)==(AdrLong >> 16)) + BEGIN + PutCode(0x02); + BAsmCode[CodeLen++] = Hi(AdrLong); + BAsmCode[CodeLen++] = Lo(AdrLong); + END + else if (MomCPU> 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> 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 (MomCPU7) 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 (MomCPU2)) 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> 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 (MomCPUMinCPU) 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 (MomCPUMinCPU) 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 (MomCPUMinCPU) 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=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< +#include + +#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< +#include + +#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='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='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 ((MomCPU7) 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=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<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-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; z23)) 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=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=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 (MomCPU22)) 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; z7)) 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 (MomCPU23)) 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> 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=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; z23)) 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 (MomCPU23)) 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 (MomCPU23)) 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 (MomCPU23)) 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 (MomCPU0x1f) 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 (MomCPU23)) 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> 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 (MomCPU0xfff)) 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< +#include + +#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> 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> (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=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=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< +#include + +#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; OrderZ127) 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; OrderZ127) 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< +#include + +#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<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 ((MomCPUArgStr[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 ((MomCPUMinCPU) 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 (MomCPUMinCPU) 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 (MomCPU127)) 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 (MomCPU7) + 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; z3)) 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; z2)) 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< + +#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> 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; z15))) 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; z127))) 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< + +#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 (MomCPU127))) 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 (MomCPU127))) 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 (MomCPU127))) 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 (MomCPU127))) 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 (MomCPU127))) WrError(1370); + else + BEGIN + BAsmCode[z-1]=AdrInt & 0xff; CodeLen=z; + END + END + END + return; + END + + /* ALU-Operationen */ + + for (z=0; z='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< +#include + +#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=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=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; z127))) 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; z2)) WrError(1110); + else if (MomCPU2)) WrError(1110); + else if (MomCPU2)) WrError(1110); + else if (MomCPU11)) 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; z2)) 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=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 +#include + +#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; z2)) 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; z2)) 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; z127)) 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; z255)) 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; z2)) 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< + +#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; z2)) 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=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; z2)) 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; z3)) 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; z0x7fffl) 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; z0x7fffl) 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< 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 +#include + +#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 (MomCPUCPU68360)) + 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; zName,Asc)==0) break; + if (z>=CtRegCnt) return False; + if ((MomCPUFirstCPU) OR (MomCPU>Reg->LastCPU)) return False; + *Erg=Reg->Code; return True; +END + + static int FindICondition(char *Name) +BEGIN + int i; + + for (i=0; iName=='[') 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 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 ,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, ? */ + 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 ,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 ..., */ + BEGIN + DecodeAdr(ArgStr[1],Mdata+Mimm); + if (AdrNum==11) /* AND #.., */ + 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, ? */ + 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 (MomCPU2)) 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 (MomCPU31) + 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=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 /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 ,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 ,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 ????, ? */ + 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, ? */ + 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, ? */ + 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) 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) 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) 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) 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=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> 16; + CheckSup(); + END + END + END + return; + END; + + if (strncmp(OpPart,"DB",2)==0) + BEGIN + for (z=0; z2) 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< +#include + +#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> 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; z2) 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; z254)) 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< +#include + +#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 (MomCPU0x7f) 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 (MomCPU2) AND (MomCPU> 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> 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=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 (MomCPULPart) 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; z0) + 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> 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=-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< + +#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> 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> (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; z127) 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; z3)) 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 (MomCPU2) 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 (MomCPU2)) 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 (MomCPU127))) + 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> (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; z2)) 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; z2)) 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 (MomCPU2)) 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 (MomCPU32767)) 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 +#include +#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; zCode<<13)+(Dest<=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='A') AND (ch<='B')) Acc=ch-'A'; + END + if (Acc==0xff) WrXError(1445,ArgStr[1]); + else ActCode|=(Op->Code<='A') AND (ch<='B')) Acc=ch-'A'; + END + if (Acc==0xff) WrXError(1445,ArgStr[1]); + else ActCode|=(Op->Code<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=JmpOrderCnt) exit(255); + if ((MomCPU>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< +#include + +#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<0) + BEGIN + DiscPtr=ArgStr[1]-1; + SplittedArg=1; + END + else DiscPtr=Nil; + return True; + END + + if (ArgCnt0) + 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<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<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; InstrZId; NOPCode=0x00000000; + DivideChars=","; HasAttrs=False; + + ValidSegs=(1< +#include + +#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; *Erg0)); +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=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=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) 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> 1) << 4); + END + END + return; + END + + for (z=0; z31))) 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 +#include + +#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=-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; z127)) 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; z127)) 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< +#include + +#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< +#include + +#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 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 + +#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 (MomCPU1) 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 (MomCPUMinCPU) 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 (MomCPUMinCPU) 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; z3)) 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=StringOrderCnt)WrError(1985); + else if (MomCPU=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; z15) 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> 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 (MomCPU0x7f) 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 +#include + +#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<=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=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=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) 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) 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< +#include + +#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> 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=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< +#include + +#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; z127) 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=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) 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) 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) WrError(1360); + if (z==DefaultCondition) + BEGIN + CodeLen=1; BAsmCode[0]=0x1e; + END + else if (z127) 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< + +#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> 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)?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; z15)) 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 (MomCPU31) 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; z127))) 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 (MomCPU127))) 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> 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> 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<= 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 +#include + +#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<=Asc; p--) + if (*p=='[') break; + if (p>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=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< +#include + +#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='0') AND (Asc[2]<='7'))) + for (z=0; z'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='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> 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) 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) 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) 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=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; z16)) + 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;z3) + 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; z8)) + 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) 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< +#include + +#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; z0) 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; z0) 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=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 (p0) 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=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> 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; zLowLim8)) + 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; zLowLim8)) + 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; zLowLim8)) + 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; zLowLim8)) + 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> 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) 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) 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< +#include + +#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; z254))) 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; zTyp=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< + +#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 + ging nicht */ +/* 2. 5.1999 JMP/CALL momentan bei keinem Mitglied erlaubt */ +/* WRAPMODE eingebaut */ +/* */ +/*****************************************************************************/ + +#include "stdinc.h" + +#include +#include + +#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; z263))) 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> 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<> 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 + +#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=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> 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< +#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 +#include + +#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 +#include + +#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; z1) 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; z0)) 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> 2]=0x5000 + +(((Word)OpSize) << 9) + +(((Word)MulOrders[z].Code & 1) << 8) + +(AdrPart << 4)+HReg; + END + END + END + return; + END + + /* Bitoperationen */ + + for (z=0; z0) 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; z0) 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; z0) 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=-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 +#include + +#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=-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> 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< +#include + +#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 ((zRegCnt) 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=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=-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=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=-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=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=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> 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=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; z254))) 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; z254))) 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<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 + +#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; z0) 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 (p1) 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=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=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=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=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< +#include + +#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; zDMax) 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 (ImmVMin)) + if (FirstPassUnknown) ImmV=Instr->Min; + else + BEGIN + WrError(1315); OK=False; + END + if ((Instr->Ofs>0) AND ((ImmVOfs) OR (ImmV>31+Instr->Ofs))) + if (FirstPassUnknown) ImmV=Instr->Ofs; + else + BEGIN + WrError((ImmVOfs) ? 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<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< +#include + +#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; z1022))) 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< + +#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; z0) 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=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 ((zMaxCodeLen) + 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; z2MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + BEGIN + HVal16=EvalIntExpression(ArgStr[z],Int16,&OK); + if (OK) + for (z2=0; z2=MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + BEGIN + TranslateString(SVal); + for (z2=0; z2>2,bpos=(Pos&3)*4; + Word dig=Ch-'0'; + + w[wpos]|=(dig<16) Man[16]='\0'; + for (z=0; z4) 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; z2MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + for (z2=0; z2MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + BEGIN + if (ListGran()==1) + for (z2=0; z2MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + BEGIN + if (ListGran()==1) + for (z2=0; z2> 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> 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> 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> 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; z2MaxCodeLen) + 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; z2MaxCodeLen) + 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; z2MaxCodeLen) + BEGIN + WrError(1920); OK=False; + END + else + BEGIN + ConvertDec(DVal,TurnField); + if (ListGran()==1) + for (z2=0; z2Erg) 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 + +#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< +#include + +#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 + +#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> 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; z15))) 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; z127) 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< +#include + +#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; z127))) 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; z127))) 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< +#include + +#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 ((p0x1ff) 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; z127))) 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; z127))) 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< +#include + +#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 (p127) 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; z127) OR (AdrInt<-128))) + BEGIN + WrError(1370); CodeLen=0; + END + else BAsmCode[CodeLen++]=AdrInt & 0xff; + END + END + return; + END + + for (z=0; z127) 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< +#include + +#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< +#include + +#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=CondCnt) WrError(1360); + END + if (z127) 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) WrError(1360); + END + if (z0x70) 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< +#include + +#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='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=4) AND (*Asc_O=='(') AND (Asc_O[strlen(Asc_O)-1]==')')) + for (z=0; z=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 ((zConditionCnt) 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=0xff80)); +END + + static Boolean CodeAri(void) +BEGIN + int z; + Byte AdrByte; + Boolean OK; + + for (z=0; z0) /* 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 (MomCPU0) /* 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 (MomCPU0) /* 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; z2)) 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 ((MomCPU0) + 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> 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> 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> 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 (MomCPU0)) 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 (MomCPU0xffffff) 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> 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=-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=-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=-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 (MomCPU3) WrError(1320); + else if ((AdrByte==3) AND (MomCPU=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) + 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-.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 +\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 @ .... +\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[:]][.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} +[] / +\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 +\end{verbatim} +werden die in \verb!! 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 (=,/): + Datei : + [(m1)] ..... [(mk)] + . + . + Datei : + [(m1)] ..... [(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} + [-][.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 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 +\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 $$ +}\end{quote} +ist eine Kurzschreibweise f"ur +\begin{quote}{\tt + DB $$ 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} + MACRO [Parameterliste] + + 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} + 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} + FUNCTION ,..,, +\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 + + ELSEIF + + (evtl. weitere ELSEIFs) + ELSEIF + + 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 + ... + CASE + ... + + ... + CASE + ... + + ... + (weitere CASE-Konstrukte) + ... + CASE + ... + + ... + ELSECASE + ... + + ... + 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 +\end{verbatim} +die Zeichenfolge angibt, die vor Listingbeginn an das Ausgabeger"at +geschickt werden soll und mit +\begin{verbatim} + PRTEXIT +\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} +_ +\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} + ... + + ... + SECTION + ... + + ... + ENDSECTION [Sektionsname] + ... + + ... +\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 +\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 : +\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: . + + .. + 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 +\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 +\end{verbatim} +In dieser Form wird die Datei komplett eingebunden. +\begin{verbatim} + BINCLUDE , +\end{verbatim} +In dieser Form wird der Inhalt der Datei ab \verb!! bis zum Ende +der Datei eingebunden. +\begin{verbatim} + BINCLUDE ,, +\end{verbatim} +In dieser Form werden \verb!! Bytes ab Offset \verb!! 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: .. + + .. +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{\#}), 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 + 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} $$ & \tty{DD} $$ & Speicher in Langworten belegen \\ +\hline +\tty{DSB} $$ & \tty{DB} $$ \tty{DUP} (?) & Speicher byteweise reservieren \\ +\hline +\tty{DSW} $$ & \tty{DW} $$ \tty{DUP} (?) & Speicher wortweise reservieren \\ +\hline +\tty{DSD} $$ & \tty{DD} $$ \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 + MOWF 3 + LCALL +\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} + 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!! & 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} + : +\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 +\end{verbatim} +bzw. +\begin{verbatim} +File +\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 . +\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 [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 -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 - +\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 eprom1 -f $31 -r $0000-$1fff +p2hex eprom2 -f $31 -r $2000-$3fff +p2hex eprom3 -f $31 -r $4000-$5fff +p2hex 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 +\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 - +\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 , +\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 +\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 +\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 +\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!ä ö ü! & "a "o "u (Umlaute)\\ +\verb!Ä Ö Ü! & "A "O "U \\ +\verb!ß! & "s (scharfes s) \\ +\verb!à è ì ò ù! & \'a \'e \'i \'o \'u (Accent \\ +\verb!À È Ì Ò Ù! & \'A \'E \'I \'O \'U grave) \\ +\verb!á é í ó ú! & \`a \`e \`i \`o \`u (Accent \\ +\verb!Á É Í Ó Ú! & \`A \`E \`I \`O \`I agiu) \\ +\verb!â ê î ô û! & \^a \^e \^i \^o \^u (Accent \\ +\verb!Â Ê Î Ô Û! & \^A \^E \^I \^O \^U circonflex) \\ +\verb!ç Ç! & \c{c} \c{C}(Cedilla) \\ +\verb!ñ Ñ! & \~n \~N \\ +\verb!å Å! & \aa \AA \\ +\verb!æ &Aelig;! & \ae \AE \\ +\verb!¿ ¡! & 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: +%% +\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-.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=[,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 +\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 @ .... +\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[:]] [.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} +[] /
+\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 +\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 (=,/): + file : + [(m1)] ..... [(mk)] + . + . + file : + [(m1)] ..... [(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} + [-][.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 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
+\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 +\end{verbatim} +It is an abbreviation of +\begin{verbatim} + DB 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} + MACRO [parameter list] + + 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} + 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} + FUNCTION ,..,, +\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 + . + . + + . + . + ELSEIF + . + . + + . + . + (possibly more ELSEIFs) + + . + . + ELSEIF + . + . + + . + . + 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 + . + . + CASE + . + + . + CASE + . + + . + (further CASE blocks) + . + CASE + . + + . + ELSECASE + . + + . + 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} + _ +\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} + . + . + + . + . + SECTION + . + . + + . + . + ENDSECTION [section's name] + . + . + + . + . +\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 +\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 :
+\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: . + + . + . + 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 +\end{verbatim} +This way, the file is completely included. +\begin{verbatim} + BINCLUDE , +\end{verbatim} +This way, the file's contents are included starting at \tty{} up to +the file's end. +\begin{verbatim} + BINCLUDE ,, +\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: + . + . + + . + . +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!#!) 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 + 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 +($0warning + 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 + MOWF 3 + LCALL +\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} + 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!! & 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} + :
+\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 +\end{verbatim} +resp. +\begin{verbatim} +File . +\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 +\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 +\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 [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 -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 - +\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 eprom1 -f $31 -r $0000-$1fff +p2hex eprom2 -f $31 -r $2000-$3fff +p2hex eprom3 -f $31 -r $4000-$5fff +p2hex 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 . +\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 - +\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
+\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 . +\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 +\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 +\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!ä ö ü! & "a "o "u (Umlaute)\\ +\verb!Ä Ö Ü! & "A "O "U \\ +\verb!ß! & "s (scharfes s) \\ +\verb!à è ì ò ù! & \'a \'e \'i \'o \'u (Accent \\ +\verb!À È Ì Ò Ù! & \'A \'E \'I \'O \'U grave) \\ +\verb!á é í ó ú! & \`a \`e \`i \`o \`u (Accent \\ +\verb!Á É Í Ó Ú! & \`A \`E \`I \`O \`I agiu) \\ +\verb!â ê î ô û! & \^a \^e \^i \^o \^u (Accent \\ +\verb!Â Ê Î Ô Û! & \^A \^E \^I \^O \^U circonflex) \\ +\verb!ç Ç! & \c{c} \c{C}(Cedilla) \\ +\verb!ñ Ñ! & \~n \~N \\ +\verb!å Å! & \aa \AA \\ +\verb!æ &Aelig;! & \ae \AE \\ +\verb!¿ ¡! & 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 + +#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>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 +#include + +#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; zsepcnts[z]>0) break; + if (zDaughters[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; zDaughters[z++]=Nil); + for (z=0; zsepcnts[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='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; zDaughters[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; zDaughters[GetIndex(Field[z2])]; + if (Lauf==Nil) break; +#ifdef DEBUG + for (z3=0; z3sepcnts[z3]>0) break; + if (z3sepcnts[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; z0) AND ((Res[z+1])&1)) putchar('-'); + putchar(Field[z+1]); + END + puts(""); +#endif + + *posis=(int *) malloc(sizeof(int)*l); *posicnt=0; + for (z=3; z0) 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 + +/* +% 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' 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 : +% To get correct hyphenation points within words containing +% umlauts or \ss, it's necessary to assign values > 0 to the +% appropriate \lccode 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 + +#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 + +#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<>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-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<"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<"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 +#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ämer" + "Not owner" + +Message IoErr_ENOENT + "Datei oder Verzeichnis nicht gefunden" + "No such file or directory" + +Message IoErr_ESRCH + "Prozeß 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ä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ültiger Dateihandle" + "No children" + +Message IoErr_ECHILD + "Tochterprozeß existiert nicht" + "Operation would cause deadlock" + +Message IoErr_EDEADLK + "Operation würde Deadlock verursachen" + "Operation would cause deadlock" + +Message IoErr_ENOMEM + "Speicherüberlauf" + "Not enough core" + +Message IoErr_EACCES + "Zugriff verweigert" + "Permission denied" + +Message IoErr_EFAULT + "Adreßfehler" + "Bad address" + +Message IoErr_ENOTBLK + "Blockgerät erforderlich" + "Block device required" + +Message IoErr_EBUSY + "Gerät blockiert" + "Device or resource busy" + +Message IoErr_EEXIST + "Datei existiert bereits" + "File exists" + +Message IoErr_EXDEV + "Link über verschiedene Geräte" + "Cross-device link" + +Message IoErr_ENODEV + "Gerä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ültiges Argument" + "Invalid argument" + +Message IoErr_ENFILE + "Dateitabellenü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ß" + "File too large" + +Message IoErr_ENOSPC + "Dateisystem voll" + "No space left on device" + +Message IoErr_ESPIPE + "Ungü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ßerhalb Definitionsbereich" + "Math argument out of domain of func" + +Message IoErr_ERANGE + "Funktionsergebnis außerhalb Wertebereich" + "Math result not representable" + +Message IoErr_ENAMETOOLONG + "Dateiname zu lang" + "File name too long" + +Message IoErr_ENOLCK + "Datensatzverieglung nicht mö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ürde blockieren" + "Operation would block" + +Message IoErr_ENOMSG + "keine Nachricht gewünschten Typs verfügbar" + "No message of desired type" + +Message IoErr_EIDRM + "Kennung entfernt" + "Identifier removed" + +Message IoErr_ECHRNG + "Kanalnummer auß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ückgesetzt" + "Level 3 reset" + +Message IoErr_ELNRNG + "Link-Nummer außerhalb Bereich" + "Link number out of range" + +Message IoErr_EUNATCH + "Protokolltreiber nicht angebunden" + "Protocol driver not attached" + +Message IoErr_ENOCSI + "keine CSI-Struktur verfü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 +#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 (NumMsgCount)) 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; zMsgCount=(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; zMsgCount; 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 +#include +#include + +#ifdef LOCALE_NLS +#include +#include +#endif + +#ifdef OS2_NLS +#define INCL_DOSNLS +#include +#endif + +#ifdef DOS_NLS +#include +#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) ] [ 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 [,] + +Add 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 + +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 |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 < - > + +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 +and +.B +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
+ +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] + +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 +#include + +#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> 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>%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; z4)) 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üfsumme: " + "checksum: " + +Message InfoMessHead2 + " [Optionen]" + " [options]" + +Message InfoMessHelp + "\n" \ + "Optionen: -f : auszufilternde Records\n" \ + " -r - : auszufilternder Adreßbereich\n" \ + " ($ = erste bzw. letzte auftauchende Adresse)\n" \ + " -l <8-Bit-Zahl> : Inhalt unbenutzter Speicherzellen festlegen\n" \ + " -s : Prüfsumme in Datei ablegen\n" \ + " -m : EPROM-Modus (odd,even,byte0..byte3)\n" \ + " -e : Startadresse festlegen\n" \ + " -S [L|B] : Startadresse voranstellen\n" \ + " -k : Quelldateien automatisch löschen\n" + "\n" \ + "options: -f
: records to filter out\n" \ + " -r - : 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 : EPROM-mode (odd,even,byte0..byte3)\n" \ + " -e
: set entry address\n" \ + " -S [L|B] : 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) ] [ 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 < - > +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
+ +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 + +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 [,] + +Add 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 + +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 < - > + +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 +and +.B +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 +#include + +#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>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=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ßüberlauf " + "warning: address overflow " + +;------------------------------------------------------------------------------ +; Ansagen + +Message InfoMessHead2 + " [Optionen]" + " [options]" + +Message InfoMessHelp + "\n" \ + "Optionen: -f : auszufilternde Records\n" \ + " -r - : auszufilternder Adreßbereich\n" \ + " -R : Adressen um Offset verschieben\n" \ + " ($ = erste bzw. letzte auftauchende Adresse)\n" \ + " -a : Adressen relativ zum Start ausgeben\n" \ + " -l : Länge Datenzeile/Bytes\n" \ + " -i <0|1|2> : Terminierer für Intel-Hexfiles\n" \ + " -m <0..3> : Multibyte-Modus\n" \ + " -F : Zielformat\n" \ + " +5 : S5-Records unterdrücken\n" \ + " -s : S-Record-Gruppen einzeln terminieren\n" \ + " -M <1|2|3> : Minimallaenge Adressen S-Records\n" \ + " -d - : Datenbereich festlegen\n" \ + " -e : Startadresse festlegen\n" \ + " -k : Quelldateien autom. löschen\n" + "\n" \ + "options: -f
: records to filter out\n" \ + " -r - : address range to filter out\n" \ + " -R : relocate addresses by offset\n" \ + " ($ = first resp. last occuring address)\n" \ + " -a : addresses in hex file relativ to start\n" \ + " -l : 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 : 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 - : set data range\n" \ + " -e
: 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) ] [ 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 [,] +Add 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 +#include + +#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 + " [Optionen]" + " [options]" + +Message InfoMessHelp + "\n" \ + "Optionen: -f : auszufilternde Records" + "\n" \ + "options: -f
: 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 + +#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ä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 + " " + " " + +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 +#include + +#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[]={ + {"ä",CH_ae}, + {"ë",CH_ee}, + {"ï",CH_ie}, + {"ö",CH_oe}, + {"ü",CH_ue}, + {"Ä",CH_Ae}, + {"Ë",CH_Ee}, + {"Ï",CH_Ie}, + {"Ö",CH_Oe}, + {"Ü",CH_Ue}, + {"ß",CH_sz}, + {"²",CH_e2}, + {"µ",CH_mu}, + {"à",CH_agrave}, + {"À",CH_Agrave}, + {"è",CH_egrave}, + {"È",CH_Egrave}, + {"ì",CH_igrave}, + {"Ì",CH_Igrave}, + {"ò",CH_ograve}, + {"Ò",CH_Ograve}, + {"ù",CH_ugrave}, + {"Ù",CH_Ugrave}, + {"á",CH_aacute}, + {"Á",CH_Aacute}, + {"é",CH_eacute}, + {"É",CH_Eacute}, + {"í",CH_iacute}, + {"Í",CH_Iacute}, + {"ó",CH_oacute}, + {"Ó",CH_Oacute}, + {"ú",CH_uacute}, + {"Ú",CH_Uacute}, + {"â",CH_acirc}, + {"Â",CH_Acirc}, + {"ê",CH_ecirc}, + {"Ê",CH_Ecirc}, + {"î",CH_icirc}, + {"Î",CH_Icirc}, + {"ô",CH_ocirc}, + {"Ô",CH_Ocirc}, + {"û",CH_ucirc}, + {"Û",CH_Ucirc}, + {"ç",CH_ccedil}, + {"Ç",CH_Ccedil}, + {"ñ",CH_ntilde}, + {"Ñ",CH_Ntilde}, + {"å",CH_aring}, + {"Å",CH_Aring}, + {"æ",CH_aelig}, + {"&Aelig;",CH_Aelig}, + {"¿",CH_iquest}, + {"¡",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; zMessages=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; zCtryName,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; zAbbString!=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 [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; c0) + BEGIN + TmpCat=MsgCats[0]; MsgCats[0]=MsgCats[DefCat]; MsgCats[DefCat]=TmpCat; + END + + /* Startadressen String-Kataloge berechnen */ + + RunPos=ftell(MsgFile)+1; + for (z=MsgCats; zHeadLength=strlen(z->CtryName)+1+4+4+(4*z->CtryCodeCnt)+4); + for (z=MsgCats; zFilePos=RunPos; RunPos+=z->TotLength+(4*MsgCounter); + END + + /* Country-Records schreiben */ + + for (z=MsgCats; zCtryName,1,strlen(z->CtryName)+1,MsgFile); + Write4(MsgFile,&(z->TotLength)); + Write4(MsgFile,&(z->CtryCodeCnt)); + for (c=0; cCtryCodeCnt; c++) Write4(MsgFile,z->CtryCodes+c); + Write4(MsgFile,&(z->FilePos)); + END + Save='\0'; fwrite(&Save,1,1,MsgFile); + + /* Stringtabellen schreiben */ + + for (z=MsgCats; zMessages; 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 +#include +#include "stdhandl.h" + +#if defined ( __EMX__ ) || defined ( __IBMC__ ) +#include +#endif + +#ifdef __TURBOC__ +#include +#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 +#ifndef __MUNIX__ +#include +#endif +#if !defined ( __MSDOS__ ) && !defined( __IBMC__ ) +#include +#endif +#include +#include +#include +#ifdef __MSDOS__ +#include +#else +#include +#ifndef __FreeBSD__ +#include +#endif +#endif + +#include "pascstyle.h" +#include "datatypes.h" +#include "chardefs.h" + +#ifndef min +#define min(a,b) ((ab)?(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 +#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 +#include + +#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)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 + + 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 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 Binary files /dev/null and b/tests/t_166/t_166.ori differ diff --git a/tests/t_16c5x/asflags b/tests/t_16c5x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_16c5x/t_16c5x.ori differ diff --git a/tests/t_16c84/asflags b/tests/t_16c84/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_16c84/t_16c84.ori differ diff --git a/tests/t_17c42/asflags b/tests/t_17c42/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_17c42/t_17c42.ori differ diff --git a/tests/t_251/asflags b/tests/t_251/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_251/t_251.ori differ diff --git a/tests/t_296/asflags b/tests/t_296/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_296/t_296.ori differ diff --git a/tests/t_29k/asflags b/tests/t_29k/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_29k/t_29k.ori differ diff --git a/tests/t_32/asflags b/tests/t_32/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_32/t_32.ori differ diff --git a/tests/t_3201x/asflags b/tests/t_3201x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_3201x/t_3201x.ori differ diff --git a/tests/t_3203x/asflags b/tests/t_3203x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_3203x/t_3203x.ori differ diff --git a/tests/t_3205x/asflags b/tests/t_3205x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_3205x/t_3205x.ori differ diff --git a/tests/t_3206x/asflags b/tests/t_3206x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_3206x/t_3206x.ori differ diff --git a/tests/t_370/asflags b/tests/t_370/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_370/t_370.ori differ diff --git a/tests/t_4004/asflags b/tests/t_4004/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_4004/t_4004.ori differ diff --git a/tests/t_403/asflags b/tests/t_403/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_403/t_403.ori differ diff --git a/tests/t_4500/asflags b/tests/t_4500/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_4500/t_4500.ori differ diff --git a/tests/t_47c00/asflags b/tests/t_47c00/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_47c00/t_47c00.ori differ diff --git a/tests/t_48/asflags b/tests/t_48/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_48/t_48.ori differ diff --git a/tests/t_56000/asflags b/tests/t_56000/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_56000/t_56000.ori differ diff --git a/tests/t_56300/asflags b/tests/t_56300/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_56300/t_56300.ori differ diff --git a/tests/t_65/asflags b/tests/t_65/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_65/t_65.ori differ diff --git a/tests/t_6502u/asflags b/tests/t_6502u/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6502u/t_6502u.ori differ diff --git a/tests/t_6804/asflags b/tests/t_6804/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6804/t_6804.ori differ diff --git a/tests/t_68040/asflags b/tests/t_68040/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_68040/t_68040.ori differ diff --git a/tests/t_6805/asflags b/tests/t_6805/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6805/t_6805.ori differ diff --git a/tests/t_6808/asflags b/tests/t_6808/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6808/t_6808.ori differ diff --git a/tests/t_6812/asflags b/tests/t_6812/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6812/t_6812.ori differ diff --git a/tests/t_6816/asflags b/tests/t_6816/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_6816/t_6816.ori differ diff --git a/tests/t_7000/asflags b/tests/t_7000/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_7000/t_7000.ori differ diff --git a/tests/t_75k0/asflags b/tests/t_75k0/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_75k0/t_75k0.ori differ diff --git a/tests/t_7700/asflags b/tests/t_7700/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_7700/t_7700.ori differ diff --git a/tests/t_7720/asflags b/tests/t_7720/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_7720/t_7720.ori differ diff --git a/tests/t_77230/asflags b/tests/t_77230/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_77230/t_77230.ori differ diff --git a/tests/t_7725/asflags b/tests/t_7725/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_7725/t_7725.ori differ diff --git a/tests/t_78c1x/asflags b/tests/t_78c1x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_78c1x/t_78c1x.ori differ diff --git a/tests/t_78k0/asflags b/tests/t_78k0/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_78k0/t_78k0.ori differ diff --git a/tests/t_85/asflags b/tests/t_85/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_85/t_85.ori differ diff --git a/tests/t_87c800/asflags b/tests/t_87c800/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_87c800/t_87c800.ori differ diff --git a/tests/t_8x30x/asflags b/tests/t_8x30x/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_8x30x/t_8x30x.ori differ diff --git a/tests/t_96/asflags b/tests/t_96/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_96/t_96.ori differ diff --git a/tests/t_960/asflags b/tests/t_960/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_960/t_960.ori differ diff --git a/tests/t_97c241/asflags b/tests/t_97c241/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_97c241/t_97c241.ori differ diff --git a/tests/t_9900/asflags b/tests/t_9900/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_9900/t_9900.ori differ diff --git a/tests/t_ace/asflags b/tests/t_ace/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_ace/t_ace.ori differ diff --git a/tests/t_avr/asflags b/tests/t_avr/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_avr/t_avr.ori differ diff --git a/tests/t_bas52/asflags b/tests/t_bas52/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_bas52/t_bas52.ori differ diff --git a/tests/t_buf32/asflags b/tests/t_buf32/asflags new file mode 100644 index 0000000..e69de29 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: +;** [...] +;** [] implies contents optional. +;** means whitespace character (space,comma,tab). +;** = command string of 1-8 characters. +;** = Argument particular to the command. +;** = 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 [-][] . . . +;* 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 Inserts . +;* break - Deletes . +;* 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 [ []] - Dump memory +;* in 16 byte lines from to . +;* 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 [] - 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 [] - Execute a jsr to 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 = + +;*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 [] - Execute starting at 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 = +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 - 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 - Trace instructions until +;*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 [] 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 [] Block fill." + FCB $0D + FCC "BR [-][] Set up breakpoint table." + FCB $0D + FCC "BULK Erase the EEPROM. BULKALL Erase EEPROM and CONFIG." + FCB $0D + FCC "CALL [] Call user subroutine. G [] Execute user code." + FCB $0D + FCC "LOAD, VERIFY [T] Load or verify S-records." + FCB $0D + FCC "MD [ []] Memory dump." + FCB $0D + FCC "MM [] 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. O Compute offset to ." + FCB $0D + FCC "MOVE [] 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 [] 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 [] +;* []/ +;* Opens memory and allows user to modify the +;*contents at or the last opened location. +;* Subcommands: +;* [] - Close current location and exit. +;* [] - Close current and open next. +;* []<^> - Close current and open previous. +;* [] - Close current and open next. +;* []/ - Reopen current location. +;* The contents of the current location is only +;* changed if valid data is entered before each +;* subcommand. +;* []O - Compute relative offset from current +;* location to . 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 [] - move +;*block at to to . +;* Moves block 1 byte up if no . +;********** +;*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 [] - prints the user regs +;*and opens them for modification. is +;*the first register opened (default = P). +;* Subcommands: +;* [] Opens the next register. +;* [] Return. +;* The register value is only changed if +;* 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 +;* 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: +;* -Carriage return finds the next opcode for +;* assembly. If there was no assembly input, +;* the next opcode disassembled is retrieved +;* from the disassembler. +;* -Linefeed works the same as carriage return +;* except if there was no assembly input, the +;* is incremented and the next is +;* disassembled. +;* '^' -Up arrow decrements 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] = ; 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 [ []] - 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 + 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 Binary files /dev/null and b/tests/t_buf32/t_buf32.ori differ diff --git a/tests/t_cop8/asflags b/tests/t_cop8/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_cop8/t_cop8.ori differ diff --git a/tests/t_f2mc8l/asflags b/tests/t_f2mc8l/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_f2mc8l/t_f2mc8l.ori differ diff --git a/tests/t_fl90/asflags b/tests/t_fl90/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_fl90/t_fl90.ori differ diff --git a/tests/t_fl900/asflags b/tests/t_fl900/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_fl900/t_fl900.ori 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 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 NearData,pc] + lda [AddressFour,pc] + ifdef ERRORS + lda ["" + 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}, , +; +; 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 , +; +; Dem 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 , , , +; + 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 , , +; 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 Binary files /dev/null and b/tests/t_mic51/t_mic51.ori 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 . " + 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 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 Binary files /dev/null and b/tests/t_msp/t_msp.ori 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 Binary files /dev/null and b/tests/t_parsys/t_parsys.ori differ diff --git a/tests/t_scmp/asflags b/tests/t_scmp/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_scmp/t_scmp.ori differ diff --git a/tests/t_secdrive/asflags b/tests/t_secdrive/asflags new file mode 100644 index 0000000..e69de29 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 ",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 ",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<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 Binary files /dev/null and b/tests/t_secdrive/t_secdrive.ori 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 ",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 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 Binary files /dev/null and b/tests/t_st6/t_st6.ori differ diff --git a/tests/t_st7/asflags b/tests/t_st7/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_st7/t_st7.ori differ diff --git a/tests/t_st9/asflags b/tests/t_st9/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_st9/t_st9.ori differ diff --git a/tests/t_tms7/asflags b/tests/t_tms7/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_tms7/t_tms7.ori differ diff --git a/tests/t_xa/asflags b/tests/t_xa/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_xa/t_xa.ori differ diff --git a/tests/t_z380/asflags b/tests/t_z380/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_z380/t_z380.ori differ diff --git a/tests/t_z8/asflags b/tests/t_z8/asflags new file mode 100644 index 0000000..e69de29 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 Binary files /dev/null and b/tests/t_z8/t_z8.ori 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 +#include +#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; zNext) + 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=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; z0) + 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)) + 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; colzsumlen) + BEGIN + diff=ml+4-sumlen; + ThisTable.ColLens[firsttext]+=diff; + END + + /* print rows */ + + for (rowz=0; rowz0) 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=CHAPMAX) return; + + FlushLine(); fputc('\n',outfile); + + assert_token("{"); LastLevel=Level; + SaveEnv(EnvHeading); RightMargin=200; + + Chapters[Level]++; + for (z=Level+1; zNext=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=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=TABMAX) error("too many tab stops"); + + n=strlen(OutLineBuffer); + for (p=0; pn) 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 \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; z0) 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; zHTML */ +/* */ +/* 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 +#include +#include +#include +#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<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,"%s\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=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="<"; + else if (strcmp(Part,">")==0) Part=">"; + else if (strcmp(Part,"&")==0) Part="&"; + + 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",(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)) + 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; colzsumlen) + BEGIN + diff=ml+4-sumlen; + ThisTable.ColLens[firsttext]+=diff; + END + + /* tell browser to switch to table mode */ + + fprintf(outfile,"

\n"); + + /* print rows */ + + rowz=0; + while (rowz\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("
\n",outfile); + END + + /* end column */ + + fprintf(outfile,"\n",ColTag); + + colptr++; + END + + /* end row */ + + fprintf(outfile,"\n"); + + rowz=rowz2+1; + END + END + + /* end table mode */ + + fprintf(outfile,"
\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",""); FlushLine(); + AddLine("",""); + PrFontDiff(0,CurrFontFlags); + END + else + BEGIN + if (*OutLineBuffer=='\0') strcpy(OutLineBuffer," "); + AddLine("
",""); FlushLine(); + END +END + + static void TeXKillLine(Word Index) +BEGIN + ResetLine(); + if (CurrEnv==EnvTabbing) + BEGIN + AddLine("",""); + 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) return; + + FlushLine(); fputc('\n',outfile); + + assert_token("{"); LastLevel=Level; + SaveEnv(EnvHeading); RightMargin=200; + + Chapters[Level]++; + for (z=Level+1; z", Level + 1); + + run = Line; + if (Level < 3) + BEGIN + GetSectionName(Ref); + for (rep = Ref; *rep != '\0'; rep++) + if (*rep == '.') *rep = '_'; + fprintf(outfile, "", Ref); + run = GetSectionName(run); + run += sprintf(run, " "); + END + sprintf(run, "%s", Title); + + fprintf(outfile, "%s", Line); + + if (Level < 3) + BEGIN + fputs("", outfile); + run = Line; run = GetSectionName(run); + run += sprintf(run," "); sprintf(run, "%s", Title); + AddToc(Line); + END + + fprintf(outfile, "\n", Level + 1); +END + + static EnvType GetEnvType(char *Name) +BEGIN + EnvType z; + + for (z=EnvNone+1; z\n",outfile); + fputs("\n",outfile); + break; + case EnvItemize: + FlushLine(); fprintf(outfile,"
    \n"); + ++CurrListDepth; + ActLeftMargin=LeftMargin=(CurrListDepth*4)+1; + RightMargin=70; + EnumCounter=0; + InListItem=False; + break; + case EnvDescription: + FlushLine(); fprintf(outfile,"
    \n"); + ++CurrListDepth; + ActLeftMargin=LeftMargin=(CurrListDepth*4)+1; + RightMargin=70; + EnumCounter=0; + InListItem=False; + break; + case EnvEnumerate: + FlushLine(); fprintf(outfile,"
      \n"); + ++CurrListDepth; + ActLeftMargin=LeftMargin=(CurrListDepth*4)+1; + RightMargin=70; + EnumCounter=0; + InListItem=False; + break; + case EnvBiblio: + FlushLine(); fprintf(outfile,"

      \n"); + fprintf(outfile,"

      %s

      \n
      \n",BiblioName); + assert_token("{"); ReadToken(Add); assert_token("}"); + ActLeftMargin=LeftMargin=4+(BibIndent=strlen(Add)); + AddToc(BiblioName); + break; + case EnvVerbatim: + FlushLine(); fprintf(outfile,"
      \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,"<",4);
      +             p+=4;
      +            END
      +           else if (*p=='>')
      +            BEGIN
      +             memmove(p+3,p,strlen(p)+1);
      +             memcpy(p,">",4);
      +             p+=4;
      +            END
      +           else p++;
      +          fprintf(outfile,"%s",Add);
      +         END
      +       END
      +      while (NOT done);
      +      fprintf(outfile,"\n
      \n"); + break; + case EnvQuote: + FlushLine(); fprintf(outfile,"
      \n"); + ActLeftMargin=LeftMargin=5; + RightMargin=70; + break; + case EnvTabbing: + FlushLine(); fputs("\n",outfile); + TabStopCnt=0; CurrTabStop=0; RightMargin=TOKLEN-1; + AddLine("",""); FlushLine(); + fputs("
      ",""); + 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("
      \n",outfile); + break; + case EnvRaggedRight: + FlushLine(); + fputs("
      \n",outfile); + break; + case EnvRaggedLeft: + FlushLine(); + fputs("
      \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("\n",outfile); + break; + case EnvItemize: + if (InListItem) AddLine("",""); + FlushLine(); fprintf(outfile,"\n"); + break; + case EnvDescription: + if (InListItem) AddLine("",""); + FlushLine(); fprintf(outfile,"\n"); + break; + case EnvEnumerate: + if (InListItem) AddLine("",""); + FlushLine(); fprintf(outfile,"\n"); + break; + case EnvQuote: + FlushLine(); fprintf(outfile,"\n"); + break; + case EnvBiblio: + FlushLine(); fprintf(outfile,"\n"); + break; + case EnvTabbing: + PrFontDiff(CurrFontFlags,0); + AddLine("
      ",outfile); + break; + case EnvCenter: + FlushLine(); + fputs("\n",outfile); + break; + case EnvRaggedRight: + case EnvRaggedLeft: + FlushLine(); + fputs("\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) ? "" : "",""); + FlushLine(); + InListItem=True; + switch(CurrEnv) + BEGIN + case EnvItemize: + fprintf(outfile,"
    1. "); + LeftMargin=ActLeftMargin-3; + break; + case EnvEnumerate: + fprintf(outfile,"
    2. "); + LeftMargin=ActLeftMargin-4; + break; + case EnvDescription: + ReadToken(Token); + if (strcmp(Token,"[")!=0) BackToken(Token); + else + BEGIN + collect_token(Acc,"]"); + LeftMargin=ActLeftMargin-4; + fprintf(outfile,"
      %s",Acc); + END + fprintf(outfile,"
      "); + 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("
      ",""); ++BibCounter; + + LeftMargin=ActLeftMargin-BibIndent-3; + sprintf(Value,"",Name); + DoAddNormal(Value,""); + sprintf(NumString,"[%*d]
      ",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("ß",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("µ",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<
      ",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,"",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",(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; pn) break; + for (z=TabStopCnt-1; z>=p; z--) TabStops[z+1]=TabStops[z]; + TabStops[p]=n; TabStopCnt++; + + PrFontDiff(CurrFontFlags,0); + DoAddNormal("",""); + 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("",""); + 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,"",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,"",Name); + DoAddNormal(HRef,BackSepString); + DoAddNormal(Value,""); + DoAddNormal("",""); +END + + static void TeXWriteCitation(Word Index) +BEGIN + char Name[TOKLEN],Value[TOKLEN],HRef[TOKLEN]; + + assert_token("{"); collect_token(Name,"}"); + GetCite(Name,Value); + sprintf(HRef,"",Name); + DoAddNormal(HRef,BackSepString); + sprintf(Name,"[%s]",Value); + DoAddNormal(Name,""); + DoAddNormal("",""); +END + + static void TeXNewParagraph(Word Index) +BEGIN + FlushLine(); + fprintf(outfile,"

      \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,"

      \n

      %s

      \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,"

      ",Level); + if (*Ref!='\0') fprintf(outfile,"",Ref); + fputs(Line,outfile); + if (*Ref!='\0') fprintf(outfile,"",Level); + fputc('\n',outfile); + END + END + + fclose(file); +END + + static void TeXPrintIndex(Word Index) +BEGIN + PIndexSave run; + int i,rz; + + FlushLine(); + fprintf(outfile,"

      %s

      \n",IndexName); + AddToc(IndexName); + + fputs("\n",outfile); rz=0; + for (run=FirstIndex; run!=Nil; run=run->Next) + BEGIN + if ((rz%5)==0) fputs("\n",outfile); + fputs("\n",outfile); + if ((rz%5)==4) fputs("\n",outfile); + rz++; + END + if ((rz%5)!=0) fputs("\n",outfile); + fputs("
      ",outfile); + fputs(run->Name,outfile); + for (i=0; iRefCnt; i++) + fprintf(outfile," %d",run->Name,i+1,i+1); + fputs("
      \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="ä"; break; + case 'e': Repl="ë"; break; + case 'i': Repl="ï"; break; + case 'o': Repl="ö"; break; + case 'u': Repl="ü"; break; + case 'A': Repl="Ä"; break; + case 'E': Repl="Ë"; break; + case 'I': Repl="Ï"; break; + case 'O': Repl="Ö"; break; + case 'U': Repl="Ü"; break; + case 's': Repl="ß"; 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="à"; break; + case 'e': Repl="è"; break; + case 'i': Repl="ì"; break; + case 'o': Repl="ò"; break; + case 'u': Repl="ù"; break; + case 'A': Repl="À"; break; + case 'E': Repl="È"; break; + case 'I': Repl="Ì"; break; + case 'O': Repl="Ò"; break; + case 'U': Repl="Ù"; 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="á"; break; + case 'e': Repl="é"; break; + case 'i': Repl="í"; break; + case 'o': Repl="ó"; break; + case 'u': Repl="ú"; break; + case 'A': Repl="Á"; break; + case 'E': Repl="É"; break; + case 'I': Repl="Í"; break; + case 'O': Repl="Ó"; break; + case 'U': Repl="Ú"; 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="â"; break; + case 'e': Repl="ê"; break; + case 'i': Repl="î"; break; + case 'o': Repl="ô"; break; + case 'u': Repl="û"; break; + case 'A': Repl="Â"; break; + case 'E': Repl="Ê"; break; + case 'I': Repl="Î"; break; + case 'O': Repl="Ô"; break; + case 'U': Repl="Û"; 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="ñ"; break; + case 'N': Repl="Ñ"; 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,"ç"); + if (strcmp(Token,"C")==0) strcpy(Token,"Ç"); + + 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="ø"; break; + case 'O': cnt=1; Repl="Ø"; break; + case 'a': + switch (Line[1]) + BEGIN + case 'a': cnt=2; Repl="å"; break; + case 'e': cnt=2; Repl="æ"; break; + default: Found=False; + END + break; + case 'A': + switch (Line[1]) + BEGIN + case 'A': cnt=2; Repl="Å"; break; + case 'E': cnt=2; Repl="Æ"; 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("¹",BackSepString); + else if (strcmp(Token,"2")==0) + DoAddNormal("²",BackSepString); + else if (strcmp(Token,"3")==0) + DoAddNormal("³",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("\n",outfile); + fputs("\n",outfile); + fputs("\n",outfile); + fprintf(outfile,"\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, "\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] \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; z0) RestoreFont(); + else if (ErrState>=0) NextErrState(); + else if (FracState>=0) NextFracState(); + else switch (CurrEnv) + BEGIN + case EnvMarginPar: + RestoreEnv(); break; + case EnvCaption: + FlushLine(); fputs("

      \n",outfile); RestoreEnv(); break; + case EnvHeading: + EndSectionHeading(); RestoreEnv(); break; + default: RestoreFont(); + END + else DoAddNormal(Line,SepString); + END + FlushLine(); + DestroyInstTable(TeXTable); + + fputs("\n",outfile); + + for (z=0; z + +#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)) + 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=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 +#include +#include +#include + +#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 [more files]\n",argv[0]); + exit(1); + } + + for (z=1; z [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 + +#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; -- cgit v1.2.3