commit 1f3e92989e4b9f3e00aaf7729b3dd2f7c044667e Author: Patrick McHardy Date: Thu Mar 3 18:44:02 2011 +0100 Import ASL Signed-off-by: Patrick McHardy 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;