├── .gitignore ├── test ├── test2.txt ├── test2.bin ├── test.bin ├── test6502.bin ├── test2.asm ├── hello.asm ├── test6502.asm ├── test6502.lst ├── test.asm └── test.lst ├── Makefile ├── LICENSE.txt ├── README.md └── gasm80.c /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | gasm80 3 | 4 | -------------------------------------------------------------------------------- /test/test2.txt: -------------------------------------------------------------------------------- 1 | ABCDEFGHIJKLMNOPQRSTUVWXYZ -------------------------------------------------------------------------------- /test/test2.bin: -------------------------------------------------------------------------------- 1 | ABCDEFGHIJKLMNOPQRSTUVWXYZFGHIJKLMNOPQRSTUVWXYZFGHIJKLM -------------------------------------------------------------------------------- /test/test.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanochess/gasm80/HEAD/test/test.bin -------------------------------------------------------------------------------- /test/test6502.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanochess/gasm80/HEAD/test/test6502.bin -------------------------------------------------------------------------------- /test/test2.asm: -------------------------------------------------------------------------------- 1 | incbin "test2.txt" 2 | incbin "test2.txt",5 3 | incbin "test2.txt",5,8 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Ultra simple makefile for gasm80 2 | # by Oscar Toledo G. 3 | # https://github.com/nanochess/gasm80 4 | # 5 | CFLAGS = -O 6 | 7 | gasm80: gasm80.c 8 | @$(CC) $(CFLAGS) gasm80.c -o $@ 9 | 10 | check: gasm80 11 | -./gasm80 test/hello.asm -o /tmp/game.rom 12 | -./gasm80 test/test.asm -o /tmp/game.rom 13 | ./gasm80 test/test6502.asm -o /tmp/game.rom 14 | 15 | clean: 16 | @rm gasm80 17 | 18 | love: 19 | @echo "...not war" 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Gasm80 (Generic Z80 Assembler) 2 | Copyright (c) 2024 Oscar Toledo G. http://nanochess.org/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /test/hello.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Hello World for Colecovision 3 | ; 4 | ; by Oscar Toledo G. 5 | ; https://nanochess.org/ 6 | ; 7 | ; Creation date: May/03/2024. 8 | ; 9 | 10 | TURN_OFF_SOUND: equ $1fd6 11 | WRITE_REGISTER: equ $1fd9 12 | FILL_VRAM: equ $1f82 13 | WRITE_VRAM: equ $1fdf 14 | 15 | org $8000 16 | 17 | db $55,$aa 18 | dw 0 19 | dw 0 20 | dw 0 21 | dw 0 22 | dw START 23 | 24 | jp 0 ; rst $08 25 | jp 0 ; rst $10 26 | jp 0 ; rst $18 27 | jp 0 ; rst $20 28 | jp 0 ; rst $28 29 | jp 0 ; rst $30 30 | jp 0 ; rst $38 31 | retn ; NMI handler 32 | nop 33 | 34 | START: 35 | call TURN_OFF_SOUND 36 | ld bc,$0000 37 | call WRITE_REGISTER 38 | ld bc,$0180 39 | call WRITE_REGISTER 40 | ld bc,$0206 41 | call WRITE_REGISTER 42 | ld bc,$0380 43 | call WRITE_REGISTER 44 | ld bc,$0400 45 | call WRITE_REGISTER 46 | ld bc,$0536 47 | call WRITE_REGISTER 48 | ld bc,$0607 49 | call WRITE_REGISTER 50 | ld bc,$0704 51 | call WRITE_REGISTER 52 | ld bc,$03F0 ; Size of characters table. 53 | ld de,$00E8 ; Pointer to VRAM. 54 | ld hl,$158B ; Direct access to Colecovision ROM 55 | call WRITE_VRAM ; Copy character table. 56 | ld hl,$2000 ; Color table. 57 | ld de,32 ; All characters (32 bytes) 58 | ld a,$F4 ; White on blue background. 59 | call FILL_VRAM ; Fill VRAM. 60 | ld hl,$1B00 ; Sprite attribute table. 61 | ld de,128 ; 128 bytes. 62 | ld a,$D1 ; Disable all. 63 | call FILL_VRAM ; Fill VRAM. 64 | ld hl,$1800 ; Screen address in VRAM. 65 | ld de,769 66 | ld a,$20 ; Space character. 67 | call FILL_VRAM ; Fill VRAM. 68 | ld bc,22 ; 22 characters. 69 | ld de,$1945 ; Screen address in VRAM. 70 | ld hl,message ; Pointer to message. 71 | call WRITE_VRAM ; Copy data to VRAM. 72 | ld bc,$01C0 ; Enable the screen. 73 | call WRITE_REGISTER 74 | jr $ 75 | 76 | message: 77 | db "---- Hello world! ----" 78 | 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gasm80: Generic Z80/6502 assembler 2 | ### by Oscar Toledo G. Mar/03/2024 3 | 4 | [https://nanochess.org/](https://nanochess.org/) 5 | 6 | [https://github.com/nanochess/gasm80](https://github.com/nanochess/gasm80) 7 | 8 | Gasm80 is a small assembler for Z80/6502 programs. It was developed to support my new CVBasic compiler for Colecovision, in order to have a complete toolchain that can work in macOS and Linux. 9 | 10 | It was developed in a single day based on my tinyasm 8088 assembler available at [https://github.com/nanochess/tinyasm](https://github.com/nanochess/tinyasm) 11 | 12 | It uses a command line syntax similar to nasm: 13 | 14 | gasm80 game.asm -o game.rom -l game.lst -s game.sym 15 | 16 | There is also the -d option for defining labels: 17 | 18 | -dLABEL 19 | -dANOTHER_LABEL=1 20 | 21 | The option -sms will patch the final ROM with a valid Sega Master System checksum at the offset 0x7ffa, just make sure your assembler file has the right header at 0x7ff0-0x7fff (CVBasic has a sample header in _cvbasic_epilogue.asm_) 22 | 23 | It returns a non-zero error code when the assembled file generates errors. 24 | 25 | ### Supported directives 26 | 27 | Labels are started with letter, number sign, underscore or period. Case is insensitive. 28 | 29 | Local labels are supported, and should start with period. The local labels final name is derived from concatenation of the last global label (not starting with period) and the local label. 30 | 31 | There is only support for Z80 and 6502 processors, and only are implemented the following directives: 32 | 33 | IFDEF 34 | IFNDEF 35 | IF 36 | ELSE 37 | ENDIF 38 | INCLUDE 39 | INCLINE 40 | INCBIN 41 | TIMES 42 | CPU Z80 43 | CPU 6502 44 | EQU 45 | DB 46 | DW 47 | RB 48 | 49 | The following operators are implemented: 50 | 51 | | Binary OR 52 | ^ Binary XOR 53 | & Binary AND 54 | << Shift to left 55 | >> Shift to right 56 | + Addition 57 | - Subtraction 58 | * Multiplication 59 | / Division (unsigned 16-bit) 60 | % Modulo operator 61 | (expr) Parenthesis 62 | - Unary negation 63 | 64 | The following numbers are implemented: 65 | 66 | 0b0000_0100 Binary, you can use underscore (it will be ignored) 67 | 0xabcd Hexadecimal. 68 | $0abcd Hexadecimal (after $ the first digit must be a number) 69 | 'a' Character constant. 70 | 10 Decimal. 71 | $$ Start address. 72 | $ Current address. 73 | 74 | This assembler won't win a speed test ;) because the internal implementation uses a linear search for the instruction set, and it is also implemented as a kind of regular expression subset for easier coding. 75 | 76 | The assembler also supports the undocumented Z80 instructions (IXH/IXL/IYH/IYL and the SLL instruction), and the undocumented 6502 instructions. 77 | 78 | The symbol file generated is compatible with the format accepted by the OpenMSX debugger. 79 | 80 | ### Building the assembler 81 | 82 | The assembler is easily built in any platform because it uses standard C: 83 | 84 | gcc gasm80.c -o gasm80 85 | 86 | I've included test cases in the 'test' subdirectory that includes the complete Z80 and 6502 instruction set. 87 | -------------------------------------------------------------------------------- /test/test6502.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 6502 instruction set test for GASM80 3 | ; 4 | ; by Oscar Toledo G. 5 | ; https://nanochess.org/ 6 | ; 7 | ; Creation date: Aug/02/2024. 8 | ; 9 | 10 | CPU 6502 11 | 12 | BRX 13 | BPL $+5 14 | JSR $aabb 15 | BMI $+5 16 | RTI 17 | BVC $+5 18 | RTS 19 | BVS $+5 20 | BCC $+5 21 | LDY #$55 22 | LDX #$55 23 | BCS $+5 24 | CPY #$55 25 | BNE $+5 26 | CPX #$55 27 | BEQ $+5 28 | ORA ($66,X) 29 | ORA ($66),Y 30 | AND ($66,X) 31 | AND ($66),Y 32 | EOR ($66,X) 33 | EOR ($66),Y 34 | ADC ($66,X) 35 | ADC ($66),Y 36 | STA ($66,X) 37 | STA ($66),Y 38 | LDA ($66,X) 39 | LDA ($66),Y 40 | CMP ($66,X) 41 | CMP ($66),Y 42 | SBC ($66,X) 43 | SBC ($66),Y 44 | BIT $66 45 | STY $66 46 | STY $66,X 47 | LDY $66 48 | LDY $66,X 49 | CPY $66 50 | CPX $66 51 | ORA $66 52 | ORA $66,X 53 | AND $66 54 | AND $66,X 55 | EOR $66 56 | EOR $66,X 57 | ADC $66 58 | ADC $66,X 59 | STA $66 60 | STA $66,X 61 | LDA $66 62 | LDA $66,X 63 | CMP $66 64 | CMP $66,X 65 | SBC $66 66 | SBC $66,X 67 | ASL $66 68 | ASL $66,X 69 | ROL $66 70 | ROL $66,X 71 | LSR $66 72 | LSR $66,X 73 | ROR $66 74 | ROR $66,X 75 | STX $66 76 | STX $66,Y 77 | LDX $66 78 | LDX $66,Y 79 | DEC $66 80 | DEC $66,X 81 | INC $66 82 | INC $66,X 83 | PHP 84 | CLC 85 | PLP 86 | SEC 87 | PHA 88 | CLI 89 | PLA 90 | SEI 91 | DEY 92 | TYA 93 | TAY 94 | CLV 95 | INY 96 | CLD 97 | INX 98 | SED 99 | ORA #$55 100 | ORA $aabb,Y 101 | AND #$55 102 | AND $aabb,Y 103 | EOR #$55 104 | EOR $aabb,Y 105 | ADC #$55 106 | ADC $aabb,Y 107 | STA $aabb,Y 108 | LDA #$55 109 | LDA $aabb,Y 110 | CMP #$55 111 | CMP $aabb,Y 112 | SBC #$55 113 | SBC $aabb,Y 114 | ASL A 115 | ROL A 116 | LSR A 117 | ROR A 118 | TXA 119 | TXS 120 | TAX 121 | TSX 122 | DEX 123 | NOP 124 | BIT $aabb 125 | JMP ($aabb) 126 | JMP $aabb 127 | STY $aabb 128 | LDY $aabb 129 | LDY $aabb,X 130 | CPY $aabb 131 | CPX $aabb 132 | ORA $aabb 133 | ORA $aabb,X 134 | AND $aabb 135 | AND $aabb,X 136 | EOR $aabb 137 | EOR $aabb,X 138 | ADC $aabb 139 | ADC $aabb,X 140 | STA $aabb 141 | STA $aabb,X 142 | LDA $aabb 143 | LDA $aabb,X 144 | CMP $aabb 145 | CMP $aabb,X 146 | SBC $aabb 147 | SBC $aabb,X 148 | ASL $aabb 149 | ASL $aabb,X 150 | ROL $aabb 151 | ROL $aabb,X 152 | LSR $aabb 153 | LSR $aabb,X 154 | ROR $aabb 155 | ROR $aabb,X 156 | STX $aabb 157 | LDX $aabb 158 | LDX $aabb,Y 159 | DEC $aabb 160 | DEC $aabb,X 161 | INC $aabb 162 | INC $aabb,X 163 | 164 | ; Undocumented instructions 165 | SLO ($66,X) 166 | SLO ($66),Y 167 | RLA ($66,X) 168 | RLA ($66),Y 169 | SRE ($66,X) 170 | SRE ($66),Y 171 | RRA ($66,X) 172 | RRA ($66),Y 173 | SAX ($66,X) 174 | SHA ($66),Y 175 | LAX ($66,X) 176 | LAX ($66),Y 177 | DCP ($66,X) 178 | DCP ($66),Y 179 | ISC ($66,X) 180 | ISC ($66),Y 181 | SLO $66 182 | SLO $66,X 183 | RLA $66 184 | RLA $66,X 185 | SRE $66 186 | SRE $66,X 187 | RRA $66 188 | RRA $66,X 189 | SAX $66 190 | SAX $66,Y 191 | LAX $66 192 | LAX $66,Y 193 | DCP $66 194 | DCP $66,X 195 | ISC $66 196 | ISC $66,X 197 | ANC #$55 198 | SLO $aabb,Y 199 | RLA $aabb,Y 200 | ALR #$55 201 | SRE $aabb,Y 202 | ARR #$55 203 | RRA $aabb,Y 204 | ANE #$55 205 | TAS $aabb,Y 206 | LXA #$55 207 | LAS $aabb,Y 208 | SBX #$55 209 | DCP $aabb,Y 210 | USBC #$55 211 | ISC $aabb,Y 212 | SHY $aabb,X 213 | SHX $aabb,Y 214 | SLO $aabb 215 | SLO $aabb,X 216 | RLA $aabb 217 | RLA $aabb,X 218 | SRE $aabb 219 | SRE $aabb,X 220 | RRA $aabb 221 | RRA $aabb,X 222 | SAX $aabb 223 | SHA $aabb,Y 224 | LAX $aabb 225 | LAX $aabb,Y 226 | DCP $aabb 227 | DCP $aabb,X 228 | ISC $aabb 229 | ISC $aabb,X 230 | -------------------------------------------------------------------------------- /test/test6502.lst: -------------------------------------------------------------------------------- 1 | 00001 ; 2 | 00002 ; 6502 instruction set test for GASM80 3 | 00003 ; 4 | 00004 ; by Oscar Toledo G. 5 | 00005 ; https://nanochess.org/ 6 | 00006 ; 7 | 00007 ; Creation date: Aug/02/2024. 8 | 00008 ; 9 | 00009 10 | 00010 CPU 6502 11 | 00011 12 | 0000 00 00012 BRX 13 | 0001 1003 00013 BPL $+5 14 | 0003 20BBAA 00014 JSR $AABB 15 | 0006 3003 00015 BMI $+5 16 | 0008 40 00016 RTI 17 | 0009 5003 00017 BVC $+5 18 | 000B 60 00018 RTS 19 | 000C 7003 00019 BVS $+5 20 | 000E 9003 00020 BCC $+5 21 | 0010 A055 00021 LDY #$55 22 | 0012 A255 00022 LDX #$55 23 | 0014 B003 00023 BCS $+5 24 | 0016 C055 00024 CPY #$55 25 | 0018 D003 00025 BNE $+5 26 | 001A E055 00026 CPX #$55 27 | 001C F003 00027 BEQ $+5 28 | 001E 0166 00028 ORA ($66,X) 29 | 0020 1166 00029 ORA ($66),Y 30 | 0022 2166 00030 AND ($66,X) 31 | 0024 3166 00031 AND ($66),Y 32 | 0026 4166 00032 EOR ($66,X) 33 | 0028 5166 00033 EOR ($66),Y 34 | 002A 6166 00034 ADC ($66,X) 35 | 002C 7166 00035 ADC ($66),Y 36 | 002E 8166 00036 STA ($66,X) 37 | 0030 9166 00037 STA ($66),Y 38 | 0032 A166 00038 LDA ($66,X) 39 | 0034 B166 00039 LDA ($66),Y 40 | 0036 C166 00040 CMP ($66,X) 41 | 0038 D166 00041 CMP ($66),Y 42 | 003A E166 00042 SBC ($66,X) 43 | 003C F166 00043 SBC ($66),Y 44 | 003E 2466 00044 BIT $66 45 | 0040 8466 00045 STY $66 46 | 0042 9466 00046 STY $66,X 47 | 0044 A466 00047 LDY $66 48 | 0046 B466 00048 LDY $66,X 49 | 0048 C466 00049 CPY $66 50 | 004A E466 00050 CPX $66 51 | 004C 0566 00051 ORA $66 52 | 004E 1566 00052 ORA $66,X 53 | 0050 2566 00053 AND $66 54 | 0052 3566 00054 AND $66,X 55 | 0054 4566 00055 EOR $66 56 | 0056 5566 00056 EOR $66,X 57 | 0058 6566 00057 ADC $66 58 | 005A 7566 00058 ADC $66,X 59 | 005C 8566 00059 STA $66 60 | 005E 9566 00060 STA $66,X 61 | 0060 A566 00061 LDA $66 62 | 0062 B566 00062 LDA $66,X 63 | 0064 C566 00063 CMP $66 64 | 0066 D566 00064 CMP $66,X 65 | 0068 E566 00065 SBC $66 66 | 006A F566 00066 SBC $66,X 67 | 006C 0666 00067 ASL $66 68 | 006E 1666 00068 ASL $66,X 69 | 0070 2666 00069 ROL $66 70 | 0072 3666 00070 ROL $66,X 71 | 0074 4666 00071 LSR $66 72 | 0076 5666 00072 LSR $66,X 73 | 0078 6666 00073 ROR $66 74 | 007A 7666 00074 ROR $66,X 75 | 007C 8666 00075 STX $66 76 | 007E 9666 00076 STX $66,Y 77 | 0080 A666 00077 LDX $66 78 | 0082 B666 00078 LDX $66,Y 79 | 0084 C666 00079 DEC $66 80 | 0086 D666 00080 DEC $66,X 81 | 0088 E666 00081 INC $66 82 | 008A F666 00082 INC $66,X 83 | 008C 08 00083 PHP 84 | 008D 18 00084 CLC 85 | 008E 28 00085 PLP 86 | 008F 38 00086 SEC 87 | 0090 48 00087 PHA 88 | 0091 58 00088 CLI 89 | 0092 68 00089 PLA 90 | 0093 78 00090 SEI 91 | 0094 88 00091 DEY 92 | 0095 98 00092 TYA 93 | 0096 A8 00093 TAY 94 | 0097 B8 00094 CLV 95 | 0098 C8 00095 INY 96 | 0099 D8 00096 CLD 97 | 009A E8 00097 INX 98 | 009B F8 00098 SED 99 | 009C 0955 00099 ORA #$55 100 | 009E 19BBAA 00100 ORA $AABB,Y 101 | 00A1 2955 00101 AND #$55 102 | 00A3 39BBAA 00102 AND $AABB,Y 103 | 00A6 4955 00103 EOR #$55 104 | 00A8 59BBAA 00104 EOR $AABB,Y 105 | 00AB 6955 00105 ADC #$55 106 | 00AD 79BBAA 00106 ADC $AABB,Y 107 | 00B0 99BBAA 00107 STA $AABB,Y 108 | 00B3 A955 00108 LDA #$55 109 | 00B5 B9BBAA 00109 LDA $AABB,Y 110 | 00B8 C955 00110 CMP #$55 111 | 00BA D9BBAA 00111 CMP $AABB,Y 112 | 00BD E955 00112 SBC #$55 113 | 00BF F9BBAA 00113 SBC $AABB,Y 114 | 00C2 0A 00114 ASL A 115 | 00C3 2A 00115 ROL A 116 | 00C4 4A 00116 LSR A 117 | 00C5 6A 00117 ROR A 118 | 00C6 8A 00118 TXA 119 | 00C7 9A 00119 TXS 120 | 00C8 AA 00120 TAX 121 | 00C9 BA 00121 TSX 122 | 00CA CA 00122 DEX 123 | 00CB EA 00123 NOP 124 | 00CC 2CBBAA 00124 BIT $AABB 125 | 00CF 6CBBAA 00125 JMP ($AABB) 126 | 00D2 4CBBAA 00126 JMP $AABB 127 | 00D5 8CBBAA 00127 STY $AABB 128 | 00D8 ACBBAA 00128 LDY $AABB 129 | 00DB BCBBAA 00129 LDY $AABB,X 130 | 00DE CCBBAA 00130 CPY $AABB 131 | 00E1 ECBBAA 00131 CPX $AABB 132 | 00E4 0DBBAA 00132 ORA $AABB 133 | 00E7 1DBBAA 00133 ORA $AABB,X 134 | 00EA 2DBBAA 00134 AND $AABB 135 | 00ED 3DBBAA 00135 AND $AABB,X 136 | 00F0 4DBBAA 00136 EOR $AABB 137 | 00F3 5DBBAA 00137 EOR $AABB,X 138 | 00F6 6DBBAA 00138 ADC $AABB 139 | 00F9 7DBBAA 00139 ADC $AABB,X 140 | 00FC 8DBBAA 00140 STA $AABB 141 | 00FF 9DBBAA 00141 STA $AABB,X 142 | 0102 ADBBAA 00142 LDA $AABB 143 | 0105 BDBBAA 00143 LDA $AABB,X 144 | 0108 CDBBAA 00144 CMP $AABB 145 | 010B DDBBAA 00145 CMP $AABB,X 146 | 010E EDBBAA 00146 SBC $AABB 147 | 0111 FDBBAA 00147 SBC $AABB,X 148 | 0114 0EBBAA 00148 ASL $AABB 149 | 0117 1EBBAA 00149 ASL $AABB,X 150 | 011A 2EBBAA 00150 ROL $AABB 151 | 011D 3EBBAA 00151 ROL $AABB,X 152 | 0120 4EBBAA 00152 LSR $AABB 153 | 0123 5EBBAA 00153 LSR $AABB,X 154 | 0126 6EBBAA 00154 ROR $AABB 155 | 0129 7EBBAA 00155 ROR $AABB,X 156 | 012C 8EBBAA 00156 STX $AABB 157 | 012F AEBBAA 00157 LDX $AABB 158 | 0132 BEBBAA 00158 LDX $AABB,Y 159 | 0135 CEBBAA 00159 DEC $AABB 160 | 0138 DEBBAA 00160 DEC $AABB,X 161 | 013B EEBBAA 00161 INC $AABB 162 | 013E FEBBAA 00162 INC $AABB,X 163 | 0141 00163 164 | 0141 00164 ; Undocumented instructions 165 | 0141 0366 00165 SLO ($66,X) 166 | 0143 1366 00166 SLO ($66),Y 167 | 0145 2366 00167 RLA ($66,X) 168 | 0147 3366 00168 RLA ($66),Y 169 | 0149 4366 00169 SRE ($66,X) 170 | 014B 5366 00170 SRE ($66),Y 171 | 014D 6366 00171 RRA ($66,X) 172 | 014F 7366 00172 RRA ($66),Y 173 | 0151 8366 00173 SAX ($66,X) 174 | 0153 9366 00174 SHA ($66),Y 175 | 0155 A366 00175 LAX ($66,X) 176 | 0157 B366 00176 LAX ($66),Y 177 | 0159 C366 00177 DCP ($66,X) 178 | 015B D366 00178 DCP ($66),Y 179 | 015D E366 00179 ISC ($66,X) 180 | 015F F366 00180 ISC ($66),Y 181 | 0161 0766 00181 SLO $66 182 | 0163 1766 00182 SLO $66,X 183 | 0165 2766 00183 RLA $66 184 | 0167 3766 00184 RLA $66,X 185 | 0169 4766 00185 SRE $66 186 | 016B 5766 00186 SRE $66,X 187 | 016D 6766 00187 RRA $66 188 | 016F 7766 00188 RRA $66,X 189 | 0171 8766 00189 SAX $66 190 | 0173 9766 00190 SAX $66,Y 191 | 0175 A766 00191 LAX $66 192 | 0177 B766 00192 LAX $66,Y 193 | 0179 C766 00193 DCP $66 194 | 017B D766 00194 DCP $66,X 195 | 017D E766 00195 ISC $66 196 | 017F F766 00196 ISC $66,X 197 | 0181 0B55 00197 ANC #$55 198 | 0183 1BBBAA 00198 SLO $AABB,Y 199 | 0186 3BBBAA 00199 RLA $AABB,Y 200 | 0189 4B55 00200 ALR #$55 201 | 018B 5BBBAA 00201 SRE $AABB,Y 202 | 018E 6B55 00202 ARR #$55 203 | 0190 7BBBAA 00203 RRA $AABB,Y 204 | 0193 8B55 00204 ANE #$55 205 | 0195 9BBBAA 00205 TAS $AABB,Y 206 | 0198 AB55 00206 LXA #$55 207 | 019A BBBBAA 00207 LAS $AABB,Y 208 | 019D CB55 00208 SBX #$55 209 | 019F DBBBAA 00209 DCP $AABB,Y 210 | 01A2 EB55 00210 USBC #$55 211 | 01A4 FBBBAA 00211 ISC $AABB,Y 212 | 01A7 9CBBAA 00212 SHY $AABB,X 213 | 01AA 9EBBAA 00213 SHX $AABB,Y 214 | 01AD 0FBBAA 00214 SLO $AABB 215 | 01B0 1FBBAA 00215 SLO $AABB,X 216 | 01B3 2FBBAA 00216 RLA $AABB 217 | 01B6 3FBBAA 00217 RLA $AABB,X 218 | 01B9 4FBBAA 00218 SRE $AABB 219 | 01BC 5FBBAA 00219 SRE $AABB,X 220 | 01BF 6FBBAA 00220 RRA $AABB 221 | 01C2 7FBBAA 00221 RRA $AABB,X 222 | 01C5 8FBBAA 00222 SAX $AABB 223 | 01C8 9FBBAA 00223 SHA $AABB,Y 224 | 01CB AFBBAA 00224 LAX $AABB 225 | 01CE BFBBAA 00225 LAX $AABB,Y 226 | 01D1 CFBBAA 00226 DCP $AABB 227 | 01D4 DFBBAA 00227 DCP $AABB,X 228 | 01D7 EFBBAA 00228 ISC $AABB 229 | 01DA FFBBAA 00229 ISC $AABB,X 230 | 231 | 00000 ERRORS FOUND 232 | 00000 WARNINGS FOUND 233 | 234 | 00477 PROGRAM BYTES 235 | 236 | -------------------------------------------------------------------------------- /test/test.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Z80 instruction set test for GASM80 3 | ; 4 | ; by Oscar Toledo G. 5 | ; https://nanochess.org/ 6 | ; 7 | ; Creation date: Mar/03/2024. 8 | ; 9 | 10 | CPU Z80 11 | 12 | NOP 13 | LD BC,$AABB 14 | LD (BC),A 15 | INC BC 16 | INC B 17 | DEC B 18 | LD B,$55 19 | RLCA 20 | EX AF,AF' 21 | ADD HL,BC 22 | LD A,(BC) 23 | DEC BC 24 | INC C 25 | DEC C 26 | LD C,$55 27 | RRCA 28 | DJNZ $+16 29 | LD DE,$AABB 30 | LD (DE),A 31 | INC DE 32 | INC D 33 | DEC D 34 | LD D,$55 35 | RLA 36 | JR $+16 37 | ADD HL,DE 38 | LD A,(DE) 39 | DEC DE 40 | INC E 41 | DEC E 42 | LD E,$55 43 | RRA 44 | JR NZ,$+16 45 | LD HL,$AABB 46 | LD ($AABB),HL 47 | INC HL 48 | INC H 49 | DEC H 50 | LD H,$55 51 | DAA 52 | JR Z,$+16 53 | ADD HL,HL 54 | LD HL,($AABB) 55 | DEC HL 56 | INC L 57 | DEC L 58 | LD L,$55 59 | CPL 60 | JR NC,$+16 61 | LD SP,$AABB 62 | LD ($AABB),A 63 | INC SP 64 | INC (HL) 65 | DEC (HL) 66 | LD (HL),$55 67 | SCF 68 | JR C,$+16 69 | ADD HL,SP 70 | LD A,($AABB) 71 | DEC SP 72 | INC A 73 | DEC A 74 | LD A,$55 75 | CCF 76 | LD B,B 77 | LD B,C 78 | LD B,D 79 | LD B,E 80 | LD B,H 81 | LD B,L 82 | LD B,(HL) 83 | LD B,A 84 | LD C,B 85 | LD C,C 86 | LD C,D 87 | LD C,E 88 | LD C,H 89 | LD C,L 90 | LD C,(HL) 91 | LD C,A 92 | LD D,B 93 | LD D,C 94 | LD D,D 95 | LD D,E 96 | LD D,H 97 | LD D,L 98 | LD D,(HL) 99 | LD D,A 100 | LD E,B 101 | LD E,C 102 | LD E,D 103 | LD E,E 104 | LD E,H 105 | LD E,L 106 | LD E,(HL) 107 | LD E,A 108 | LD H,B 109 | LD H,C 110 | LD H,D 111 | LD H,E 112 | LD H,H 113 | LD H,L 114 | LD H,(HL) 115 | LD H,A 116 | LD L,B 117 | LD L,C 118 | LD L,D 119 | LD L,E 120 | LD L,H 121 | LD L,L 122 | LD L,(HL) 123 | LD L,A 124 | LD (HL),B 125 | LD (HL),C 126 | LD (HL),D 127 | LD (HL),E 128 | LD (HL),H 129 | LD (HL),L 130 | HALT 131 | LD (HL),A 132 | LD A,B 133 | LD A,C 134 | LD A,D 135 | LD A,E 136 | LD A,H 137 | LD A,L 138 | LD A,(HL) 139 | LD A,A 140 | ADD A,B 141 | ADD A,C 142 | ADD A,D 143 | ADD A,E 144 | ADD A,H 145 | ADD A,L 146 | ADD A,(HL) 147 | ADD A,A 148 | ADC A,B 149 | ADC A,C 150 | ADC A,D 151 | ADC A,E 152 | ADC A,H 153 | ADC A,L 154 | ADC A,(HL) 155 | ADC A,A 156 | SUB B 157 | SUB C 158 | SUB D 159 | SUB E 160 | SUB H 161 | SUB L 162 | SUB (HL) 163 | SUB A 164 | SBC A,B 165 | SBC A,C 166 | SBC A,D 167 | SBC A,E 168 | SBC A,H 169 | SBC A,L 170 | SBC A,(HL) 171 | SBC A,A 172 | AND B 173 | AND C 174 | AND D 175 | AND E 176 | AND H 177 | AND L 178 | AND (HL) 179 | AND A 180 | XOR B 181 | XOR C 182 | XOR D 183 | XOR E 184 | XOR H 185 | XOR L 186 | XOR (HL) 187 | XOR A 188 | OR B 189 | OR C 190 | OR D 191 | OR E 192 | OR H 193 | OR L 194 | OR (HL) 195 | OR A 196 | CP B 197 | CP C 198 | CP D 199 | CP E 200 | CP H 201 | CP L 202 | CP (HL) 203 | CP A 204 | RET NZ 205 | POP BC 206 | JP NZ,$AABB 207 | JP $AABB 208 | CALL NZ,$AABB 209 | PUSH BC 210 | ADD A,$55 211 | RST 0 212 | RET Z 213 | RET 214 | JP Z,$AABB 215 | RLC B 216 | RLC C 217 | RLC D 218 | RLC E 219 | RLC H 220 | RLC L 221 | RLC (HL) 222 | RLC A 223 | RRC B 224 | RRC C 225 | RRC D 226 | RRC E 227 | RRC H 228 | RRC L 229 | RRC (HL) 230 | RRC A 231 | RL B 232 | RL C 233 | RL D 234 | RL E 235 | RL H 236 | RL L 237 | RL (HL) 238 | RL A 239 | RR B 240 | RR C 241 | RR D 242 | RR E 243 | RR H 244 | RR L 245 | RR (HL) 246 | RR A 247 | SLA B 248 | SLA C 249 | SLA D 250 | SLA E 251 | SLA H 252 | SLA L 253 | SLA (HL) 254 | SLA A 255 | SRA B 256 | SRA C 257 | SRA D 258 | SRA E 259 | SRA H 260 | SRA L 261 | SRA (HL) 262 | SRA A 263 | SRL B 264 | SRL C 265 | SRL D 266 | SRL E 267 | SRL H 268 | SRL L 269 | SRL (HL) 270 | SRL A 271 | BIT 0,B 272 | BIT 0,C 273 | BIT 0,D 274 | BIT 0,E 275 | BIT 0,H 276 | BIT 0,L 277 | BIT 0,(HL) 278 | BIT 0,A 279 | BIT 1,B 280 | BIT 1,C 281 | BIT 1,D 282 | BIT 1,E 283 | BIT 1,H 284 | BIT 1,L 285 | BIT 1,(HL) 286 | BIT 1,A 287 | BIT 2,B 288 | BIT 2,C 289 | BIT 2,D 290 | BIT 2,E 291 | BIT 2,H 292 | BIT 2,L 293 | BIT 2,(HL) 294 | BIT 2,A 295 | BIT 3,B 296 | BIT 3,C 297 | BIT 3,D 298 | BIT 3,E 299 | BIT 3,H 300 | BIT 3,L 301 | BIT 3,(HL) 302 | BIT 3,A 303 | BIT 4,B 304 | BIT 4,C 305 | BIT 4,D 306 | BIT 4,E 307 | BIT 4,H 308 | BIT 4,L 309 | BIT 4,(HL) 310 | BIT 4,A 311 | BIT 5,B 312 | BIT 5,C 313 | BIT 5,D 314 | BIT 5,E 315 | BIT 5,H 316 | BIT 5,L 317 | BIT 5,(HL) 318 | BIT 5,A 319 | BIT 6,B 320 | BIT 6,C 321 | BIT 6,D 322 | BIT 6,E 323 | BIT 6,H 324 | BIT 6,L 325 | BIT 6,(HL) 326 | BIT 6,A 327 | BIT 7,B 328 | BIT 7,C 329 | BIT 7,D 330 | BIT 7,E 331 | BIT 7,H 332 | BIT 7,L 333 | BIT 7,(HL) 334 | BIT 7,A 335 | RES 0,B 336 | RES 0,C 337 | RES 0,D 338 | RES 0,E 339 | RES 0,H 340 | RES 0,L 341 | RES 0,(HL) 342 | RES 0,A 343 | RES 1,B 344 | RES 1,C 345 | RES 1,D 346 | RES 1,E 347 | RES 1,H 348 | RES 1,L 349 | RES 1,(HL) 350 | RES 1,A 351 | RES 2,B 352 | RES 2,C 353 | RES 2,D 354 | RES 2,E 355 | RES 2,H 356 | RES 2,L 357 | RES 2,(HL) 358 | RES 2,A 359 | RES 3,B 360 | RES 3,C 361 | RES 3,D 362 | RES 3,E 363 | RES 3,H 364 | RES 3,L 365 | RES 3,(HL) 366 | RES 3,A 367 | RES 4,B 368 | RES 4,C 369 | RES 4,D 370 | RES 4,E 371 | RES 4,H 372 | RES 4,L 373 | RES 4,(HL) 374 | RES 4,A 375 | RES 5,B 376 | RES 5,C 377 | RES 5,D 378 | RES 5,E 379 | RES 5,H 380 | RES 5,L 381 | RES 5,(HL) 382 | RES 5,A 383 | RES 6,B 384 | RES 6,C 385 | RES 6,D 386 | RES 6,E 387 | RES 6,H 388 | RES 6,L 389 | RES 6,(HL) 390 | RES 6,A 391 | RES 7,B 392 | RES 7,C 393 | RES 7,D 394 | RES 7,E 395 | RES 7,H 396 | RES 7,L 397 | RES 7,(HL) 398 | RES 7,A 399 | SET 0,B 400 | SET 0,C 401 | SET 0,D 402 | SET 0,E 403 | SET 0,H 404 | SET 0,L 405 | SET 0,(HL) 406 | SET 0,A 407 | SET 1,B 408 | SET 1,C 409 | SET 1,D 410 | SET 1,E 411 | SET 1,H 412 | SET 1,L 413 | SET 1,(HL) 414 | SET 1,A 415 | SET 2,B 416 | SET 2,C 417 | SET 2,D 418 | SET 2,E 419 | SET 2,H 420 | SET 2,L 421 | SET 2,(HL) 422 | SET 2,A 423 | SET 3,B 424 | SET 3,C 425 | SET 3,D 426 | SET 3,E 427 | SET 3,H 428 | SET 3,L 429 | SET 3,(HL) 430 | SET 3,A 431 | SET 4,B 432 | SET 4,C 433 | SET 4,D 434 | SET 4,E 435 | SET 4,H 436 | SET 4,L 437 | SET 4,(HL) 438 | SET 4,A 439 | SET 5,B 440 | SET 5,C 441 | SET 5,D 442 | SET 5,E 443 | SET 5,H 444 | SET 5,L 445 | SET 5,(HL) 446 | SET 5,A 447 | SET 6,B 448 | SET 6,C 449 | SET 6,D 450 | SET 6,E 451 | SET 6,H 452 | SET 6,L 453 | SET 6,(HL) 454 | SET 6,A 455 | SET 7,B 456 | SET 7,C 457 | SET 7,D 458 | SET 7,E 459 | SET 7,H 460 | SET 7,L 461 | SET 7,(HL) 462 | SET 7,A 463 | CALL Z,$AABB 464 | CALL $AABB 465 | ADC A,$55 466 | RST 8 467 | RET NC 468 | POP DE 469 | JP NC,$AABB 470 | OUT ($55),A 471 | CALL NC,$AABB 472 | PUSH DE 473 | SUB $55 474 | RST 16 475 | RET C 476 | EXX 477 | JP C,$AABB 478 | IN A,($55) 479 | CALL C,$AABB 480 | ADD IX,BC 481 | ADD IX,DE 482 | LD IX,$AABB 483 | LD ($AABB),IX 484 | INC IX 485 | ADD IX,IX 486 | LD IX,($AABB) 487 | DEC IX 488 | INC (IX+5) 489 | DEC (IX+5) 490 | LD (IX+5),$BB 491 | ADD IX,SP 492 | LD B,(IX+5) 493 | LD C,(IX+5) 494 | LD D,(IX+5) 495 | LD E,(IX+5) 496 | LD H,(IX+5) 497 | LD L,(IX+5) 498 | LD (IX+5),B 499 | LD (IX+5),C 500 | LD (IX+5),D 501 | LD (IX+5),E 502 | LD (IX+5),H 503 | LD (IX+5),L 504 | LD (IX+5),A 505 | LD A,(IX+5) 506 | ADD A,(IX+5) 507 | ADC A,(IX+5) 508 | SUB (IX+5) 509 | SBC A,(IX+5) 510 | AND (IX+5) 511 | XOR (IX+5) 512 | OR (IX+5) 513 | CP (IX+5) 514 | RLC (IX+5) 515 | RRC (IX+5) 516 | RL (IX+5) 517 | RR (IX+5) 518 | SLA (IX+5) 519 | SRA (IX+5) 520 | SRL (IX+5) 521 | BIT 0,(IX+5) 522 | BIT 7,(IX+5) 523 | RES 0,(IX+5) 524 | RES 7,(IX+5) 525 | SET 0,(IX+5) 526 | SET 7,(IX+5) 527 | POP IX 528 | EX (SP),IX 529 | PUSH IX 530 | JP (IX) 531 | LD SP,IX 532 | SBC A,$55 533 | RST 24 534 | RET PO 535 | POP HL 536 | JP PO,$AABB 537 | EX (SP),HL 538 | CALL PO,$AABB 539 | PUSH HL 540 | AND $55 541 | RST 32 542 | RET PE 543 | JP (HL) 544 | JP PE,$AABB 545 | EX DE,HL 546 | CALL PE,$AABB 547 | IN B,(C) 548 | OUT (C),B 549 | SBC HL,BC 550 | LD ($AABB),BC 551 | NEG 552 | RETN 553 | IM 0 554 | LD I,A 555 | IN C,(C) 556 | OUT (C),C 557 | ADC HL,BC 558 | LD BC,($AABB) 559 | RETI 560 | LD R,A 561 | IN D,(C) 562 | OUT (C),D 563 | SBC HL,DE 564 | LD ($AABB),DE 565 | IM 1 566 | LD A,I 567 | IN E,(C) 568 | OUT (C),E 569 | ADC HL,DE 570 | LD DE,($AABB) 571 | IM 2 572 | LD A,R 573 | SBC HL,HL 574 | RRD 575 | ADC HL,HL 576 | RLD 577 | SBC HL,SP 578 | LD ($AABB),SP 579 | ADC HL,SP 580 | LD SP,($AABB) 581 | LDI 582 | CPI 583 | INI 584 | OUTI 585 | LDD 586 | CPD 587 | IND 588 | OUTD 589 | LDIR 590 | CPIR 591 | INIR 592 | OTIR 593 | LDDR 594 | CPDR 595 | INDR 596 | OTDR 597 | XOR $55 598 | RST 40 599 | RET P 600 | POP AF 601 | JP P,$AABB 602 | DI 603 | CALL P,$AABB 604 | PUSH AF 605 | OR $55 606 | RST $30 607 | RET M 608 | LD SP,HL 609 | JP M,$AABB 610 | EI 611 | CALL M,$AABB 612 | ADD IY,BC 613 | ADD IY,DE 614 | LD IY,$AABB 615 | LD ($AABB),IY 616 | INC IY 617 | ADD IY,IY 618 | LD IY,($AABB) 619 | DEC IY 620 | INC (IY+5) 621 | DEC (IY+5) 622 | LD (IY+5),$BB 623 | ADD IY,SP 624 | LD B,(IY+5) 625 | LD C,(IY+5) 626 | LD D,(IY+5) 627 | LD E,(IY+5) 628 | LD H,(IY+5) 629 | LD L,(IY+5) 630 | LD (IY+5),B 631 | LD (IY+5),C 632 | LD (IY+5),D 633 | LD (IY+5),E 634 | LD (IY+5),H 635 | LD (IY+5),L 636 | LD (IY+5),A 637 | LD A,(IY+5) 638 | ADD A,(IY+5) 639 | ADC A,(IY+5) 640 | SUB (IY+5) 641 | SBC A,(IY+5) 642 | AND (IY+5) 643 | XOR (IY+5) 644 | OR (IY+5) 645 | CP (IY+5) 646 | RLC (IY+5) 647 | RRC (IY+5) 648 | RL (IY+5) 649 | RR (IY+5) 650 | SLA (IY+5) 651 | SRA (IY+5) 652 | SRL (IY+5) 653 | BIT 0,(IY+5) 654 | BIT 7,(IY+5) 655 | RES 0,(IY+5) 656 | RES 7,(IY+5) 657 | SET 0,(IY+5) 658 | SET 7,(IY+5) 659 | POP IY 660 | EX (SP),IY 661 | PUSH IY 662 | JP (IY) 663 | LD SP,IY 664 | CP $55 665 | RST $38 666 | 667 | ; Undocumented instructions 668 | INC IXH 669 | DEC IXH 670 | LD IXH,$55 671 | INC IXL 672 | DEC IXL 673 | LD IXL,$55 674 | LD B,IXH 675 | LD B,IXL 676 | LD C,IXH 677 | LD C,IXL 678 | LD D,IXH 679 | LD D,IXL 680 | LD E,IXH 681 | LD E,IXL 682 | LD IXH,B 683 | LD IXH,C 684 | LD IXH,D 685 | LD IXH,E 686 | LD IXH,IXH 687 | LD IXH,IXL 688 | LD IXH,A 689 | LD IXL,B 690 | LD IXL,C 691 | LD IXL,D 692 | LD IXL,E 693 | LD IXL,IXH 694 | LD IXL,IXL 695 | LD IXL,A 696 | LD A,IXH 697 | LD A,IXL 698 | ADD A,IXH 699 | ADD A,IXL 700 | ADC A,IXH 701 | ADC A,IXL 702 | SUB IXH 703 | SUB IXL 704 | SBC A,IXH 705 | SBC A,IXL 706 | AND IXH 707 | AND IXL 708 | XOR IXH 709 | XOR IXL 710 | OR IXH 711 | OR IXL 712 | CP IXH 713 | CP IXL 714 | 715 | INC IYH 716 | DEC IYH 717 | LD IYH,$55 718 | INC IYL 719 | DEC IYL 720 | LD IYL,$55 721 | LD B,IYH 722 | LD B,IYL 723 | LD C,IYH 724 | LD C,IYL 725 | LD D,IYH 726 | LD D,IYL 727 | LD E,IYH 728 | LD E,IYL 729 | LD IYH,B 730 | LD IYH,C 731 | LD IYH,D 732 | LD IYH,E 733 | LD IYH,IYH 734 | LD IYH,IYL 735 | LD IYH,A 736 | LD IYL,B 737 | LD IYL,C 738 | LD IYL,D 739 | LD IYL,E 740 | LD IYL,IYH 741 | LD IYL,IYL 742 | LD IYL,A 743 | LD A,IYH 744 | LD A,IYL 745 | ADD A,IYH 746 | ADD A,IYL 747 | ADC A,IYH 748 | ADC A,IYL 749 | SUB IYH 750 | SUB IYL 751 | SBC A,IYH 752 | SBC A,IYL 753 | AND IYH 754 | AND IYL 755 | XOR IYH 756 | XOR IYL 757 | OR IYH 758 | OR IYL 759 | CP IYH 760 | CP IYL 761 | SLL B 762 | SLL C 763 | SLL D 764 | SLL E 765 | SLL H 766 | SLL L 767 | SLL (HL) 768 | SLL A 769 | -------------------------------------------------------------------------------- /test/test.lst: -------------------------------------------------------------------------------- 1 | 00001 ; 2 | 00002 ; Z80 instruction set test for GASM80 3 | 00003 ; 4 | 00004 ; by Oscar Toledo G. 5 | 00005 ; https://nanochess.org/ 6 | 00006 ; 7 | 00007 ; Creation date: Mar/03/2024. 8 | 00008 ; 9 | 00009 10 | 00010 CPU Z80 11 | 00011 12 | 0000 00 00012 NOP 13 | 0001 01BBAA 00013 LD BC,$AABB 14 | 0004 02 00014 LD (BC),A 15 | 0005 03 00015 INC BC 16 | 0006 04 00016 INC B 17 | 0007 05 00017 DEC B 18 | 0008 0655 00018 LD B,$55 19 | 000A 07 00019 RLCA 20 | 000B 08 00020 EX AF,AF' 21 | 22 | 000C 09 00021 ADD HL,BC 23 | 000D 0A 00022 LD A,(BC) 24 | 000E 0B 00023 DEC BC 25 | 000F 0C 00024 INC C 26 | 0010 0D 00025 DEC C 27 | 0011 0E55 00026 LD C,$55 28 | 0013 0F 00027 RRCA 29 | 0014 100E 00028 DJNZ $+16 30 | 0016 11BBAA 00029 LD DE,$AABB 31 | 0019 12 00030 LD (DE),A 32 | 001A 13 00031 INC DE 33 | 001B 14 00032 INC D 34 | 001C 15 00033 DEC D 35 | 001D 1655 00034 LD D,$55 36 | 001F 17 00035 RLA 37 | 0020 180E 00036 JR $+16 38 | 0022 19 00037 ADD HL,DE 39 | 0023 1A 00038 LD A,(DE) 40 | 0024 1B 00039 DEC DE 41 | 0025 1C 00040 INC E 42 | 0026 1D 00041 DEC E 43 | 0027 1E55 00042 LD E,$55 44 | 0029 1F 00043 RRA 45 | 002A 200E 00044 JR NZ,$+16 46 | 002C 21BBAA 00045 LD HL,$AABB 47 | 002F 22BBAA 00046 LD ($AABB),HL 48 | 0032 23 00047 INC HL 49 | 0033 24 00048 INC H 50 | 0034 25 00049 DEC H 51 | 0035 2655 00050 LD H,$55 52 | 0037 27 00051 DAA 53 | 0038 280E 00052 JR Z,$+16 54 | 003A 29 00053 ADD HL,HL 55 | 003B 2ABBAA 00054 LD HL,($AABB) 56 | 003E 2B 00055 DEC HL 57 | 003F 2C 00056 INC L 58 | 0040 2D 00057 DEC L 59 | 0041 2E55 00058 LD L,$55 60 | 0043 2F 00059 CPL 61 | 0044 300E 00060 JR NC,$+16 62 | 0046 31BBAA 00061 LD SP,$AABB 63 | 0049 32BBAA 00062 LD ($AABB),A 64 | 004C 33 00063 INC SP 65 | 004D 34 00064 INC (HL) 66 | 004E 35 00065 DEC (HL) 67 | 004F 3655 00066 LD (HL),$55 68 | 0051 37 00067 SCF 69 | 0052 380E 00068 JR C,$+16 70 | 0054 39 00069 ADD HL,SP 71 | 0055 3ABBAA 00070 LD A,($AABB) 72 | 0058 3B 00071 DEC SP 73 | 0059 3C 00072 INC A 74 | 005A 3D 00073 DEC A 75 | 005B 3E55 00074 LD A,$55 76 | 005D 3F 00075 CCF 77 | 005E 40 00076 LD B,B 78 | 005F 41 00077 LD B,C 79 | 0060 42 00078 LD B,D 80 | 0061 43 00079 LD B,E 81 | 0062 44 00080 LD B,H 82 | 0063 45 00081 LD B,L 83 | 0064 46 00082 LD B,(HL) 84 | 0065 47 00083 LD B,A 85 | 0066 48 00084 LD C,B 86 | 0067 49 00085 LD C,C 87 | 0068 4A 00086 LD C,D 88 | 0069 4B 00087 LD C,E 89 | 006A 4C 00088 LD C,H 90 | 006B 4D 00089 LD C,L 91 | 006C 4E 00090 LD C,(HL) 92 | 006D 4F 00091 LD C,A 93 | 006E 50 00092 LD D,B 94 | 006F 51 00093 LD D,C 95 | 0070 52 00094 LD D,D 96 | 0071 53 00095 LD D,E 97 | 0072 54 00096 LD D,H 98 | 0073 55 00097 LD D,L 99 | 0074 56 00098 LD D,(HL) 100 | 0075 57 00099 LD D,A 101 | 0076 58 00100 LD E,B 102 | 0077 59 00101 LD E,C 103 | 0078 5A 00102 LD E,D 104 | 0079 5B 00103 LD E,E 105 | 007A 5C 00104 LD E,H 106 | 007B 5D 00105 LD E,L 107 | 007C 5E 00106 LD E,(HL) 108 | 007D 5F 00107 LD E,A 109 | 007E 60 00108 LD H,B 110 | 007F 61 00109 LD H,C 111 | 0080 62 00110 LD H,D 112 | 0081 63 00111 LD H,E 113 | 0082 64 00112 LD H,H 114 | 0083 65 00113 LD H,L 115 | 0084 66 00114 LD H,(HL) 116 | 0085 67 00115 LD H,A 117 | 0086 68 00116 LD L,B 118 | 0087 69 00117 LD L,C 119 | 0088 6A 00118 LD L,D 120 | 0089 6B 00119 LD L,E 121 | 008A 6C 00120 LD L,H 122 | 008B 6D 00121 LD L,L 123 | 008C 6E 00122 LD L,(HL) 124 | 008D 6F 00123 LD L,A 125 | 008E 70 00124 LD (HL),B 126 | 008F 71 00125 LD (HL),C 127 | 0090 72 00126 LD (HL),D 128 | 0091 73 00127 LD (HL),E 129 | 0092 74 00128 LD (HL),H 130 | 0093 75 00129 LD (HL),L 131 | 0094 76 00130 HALT 132 | 0095 77 00131 LD (HL),A 133 | 0096 78 00132 LD A,B 134 | 0097 79 00133 LD A,C 135 | 0098 7A 00134 LD A,D 136 | 0099 7B 00135 LD A,E 137 | 009A 7C 00136 LD A,H 138 | 009B 7D 00137 LD A,L 139 | 009C 7E 00138 LD A,(HL) 140 | 009D 7F 00139 LD A,A 141 | 009E 80 00140 ADD A,B 142 | 009F 81 00141 ADD A,C 143 | 00A0 82 00142 ADD A,D 144 | 00A1 83 00143 ADD A,E 145 | 00A2 84 00144 ADD A,H 146 | 00A3 85 00145 ADD A,L 147 | 00A4 86 00146 ADD A,(HL) 148 | 00A5 87 00147 ADD A,A 149 | 00A6 88 00148 ADC A,B 150 | 00A7 89 00149 ADC A,C 151 | 00A8 8A 00150 ADC A,D 152 | 00A9 8B 00151 ADC A,E 153 | 00AA 8C 00152 ADC A,H 154 | 00AB 8D 00153 ADC A,L 155 | 00AC 8E 00154 ADC A,(HL) 156 | 00AD 8F 00155 ADC A,A 157 | 00AE 90 00156 SUB B 158 | 00AF 91 00157 SUB C 159 | 00B0 92 00158 SUB D 160 | 00B1 93 00159 SUB E 161 | 00B2 94 00160 SUB H 162 | 00B3 95 00161 SUB L 163 | 00B4 96 00162 SUB (HL) 164 | 00B5 97 00163 SUB A 165 | 00B6 98 00164 SBC A,B 166 | 00B7 99 00165 SBC A,C 167 | 00B8 9A 00166 SBC A,D 168 | 00B9 9B 00167 SBC A,E 169 | 00BA 9C 00168 SBC A,H 170 | 00BB 9D 00169 SBC A,L 171 | 00BC 9E 00170 SBC A,(HL) 172 | 00BD 9F 00171 SBC A,A 173 | 00BE A0 00172 AND B 174 | 00BF A1 00173 AND C 175 | 00C0 A2 00174 AND D 176 | 00C1 A3 00175 AND E 177 | 00C2 A4 00176 AND H 178 | 00C3 A5 00177 AND L 179 | 00C4 A6 00178 AND (HL) 180 | 00C5 A7 00179 AND A 181 | 00C6 A8 00180 XOR B 182 | 00C7 A9 00181 XOR C 183 | 00C8 AA 00182 XOR D 184 | 00C9 AB 00183 XOR E 185 | 00CA AC 00184 XOR H 186 | 00CB AD 00185 XOR L 187 | 00CC AE 00186 XOR (HL) 188 | 00CD AF 00187 XOR A 189 | 00CE B0 00188 OR B 190 | 00CF B1 00189 OR C 191 | 00D0 B2 00190 OR D 192 | 00D1 B3 00191 OR E 193 | 00D2 B4 00192 OR H 194 | 00D3 B5 00193 OR L 195 | 00D4 B6 00194 OR (HL) 196 | 00D5 B7 00195 OR A 197 | 00D6 B8 00196 CP B 198 | 00D7 B9 00197 CP C 199 | 00D8 BA 00198 CP D 200 | 00D9 BB 00199 CP E 201 | 00DA BC 00200 CP H 202 | 00DB BD 00201 CP L 203 | 00DC BE 00202 CP (HL) 204 | 00DD BF 00203 CP A 205 | 00DE C0 00204 RET NZ 206 | 00DF C1 00205 POP BC 207 | 00E0 C2BBAA 00206 JP NZ,$AABB 208 | 00E3 C3BBAA 00207 JP $AABB 209 | 00E6 C4BBAA 00208 CALL NZ,$AABB 210 | 00E9 C5 00209 PUSH BC 211 | 00EA C655 00210 ADD A,$55 212 | 00EC C7 00211 RST 0 213 | 00ED C8 00212 RET Z 214 | 00EE C9 00213 RET 215 | 00EF CABBAA 00214 JP Z,$AABB 216 | 00F2 CB00 00215 RLC B 217 | 00F4 CB01 00216 RLC C 218 | 00F6 CB02 00217 RLC D 219 | 00F8 CB03 00218 RLC E 220 | 00FA CB04 00219 RLC H 221 | 00FC CB05 00220 RLC L 222 | 00FE CB06 00221 RLC (HL) 223 | 0100 CB07 00222 RLC A 224 | 0102 CB08 00223 RRC B 225 | 0104 CB09 00224 RRC C 226 | 0106 CB0A 00225 RRC D 227 | 0108 CB0B 00226 RRC E 228 | 010A CB0C 00227 RRC H 229 | 010C CB0D 00228 RRC L 230 | 010E CB0E 00229 RRC (HL) 231 | 0110 CB0F 00230 RRC A 232 | 0112 CB10 00231 RL B 233 | 0114 CB11 00232 RL C 234 | 0116 CB12 00233 RL D 235 | 0118 CB13 00234 RL E 236 | 011A CB14 00235 RL H 237 | 011C CB15 00236 RL L 238 | 011E CB16 00237 RL (HL) 239 | 0120 CB17 00238 RL A 240 | 0122 CB18 00239 RR B 241 | 0124 CB19 00240 RR C 242 | 0126 CB1A 00241 RR D 243 | 0128 CB1B 00242 RR E 244 | 012A CB1C 00243 RR H 245 | 012C CB1D 00244 RR L 246 | 012E CB1E 00245 RR (HL) 247 | 0130 CB1F 00246 RR A 248 | 0132 CB20 00247 SLA B 249 | 0134 CB21 00248 SLA C 250 | 0136 CB22 00249 SLA D 251 | 0138 CB23 00250 SLA E 252 | 013A CB24 00251 SLA H 253 | 013C CB25 00252 SLA L 254 | 013E CB26 00253 SLA (HL) 255 | 0140 CB27 00254 SLA A 256 | 0142 CB28 00255 SRA B 257 | 0144 CB29 00256 SRA C 258 | 0146 CB2A 00257 SRA D 259 | 0148 CB2B 00258 SRA E 260 | 014A CB2C 00259 SRA H 261 | 014C CB2D 00260 SRA L 262 | 014E CB2E 00261 SRA (HL) 263 | 0150 CB2F 00262 SRA A 264 | 0152 CB38 00263 SRL B 265 | 0154 CB39 00264 SRL C 266 | 0156 CB3A 00265 SRL D 267 | 0158 CB3B 00266 SRL E 268 | 015A CB3C 00267 SRL H 269 | 015C CB3D 00268 SRL L 270 | 015E CB3E 00269 SRL (HL) 271 | 0160 CB3F 00270 SRL A 272 | 0162 CB40 00271 BIT 0,B 273 | 0164 CB41 00272 BIT 0,C 274 | 0166 CB42 00273 BIT 0,D 275 | 0168 CB43 00274 BIT 0,E 276 | 016A CB44 00275 BIT 0,H 277 | 016C CB45 00276 BIT 0,L 278 | 016E CB46 00277 BIT 0,(HL) 279 | 0170 CB47 00278 BIT 0,A 280 | 0172 CB48 00279 BIT 1,B 281 | 0174 CB49 00280 BIT 1,C 282 | 0176 CB4A 00281 BIT 1,D 283 | 0178 CB4B 00282 BIT 1,E 284 | 017A CB4C 00283 BIT 1,H 285 | 017C CB4D 00284 BIT 1,L 286 | 017E CB4E 00285 BIT 1,(HL) 287 | 0180 CB4F 00286 BIT 1,A 288 | 0182 CB50 00287 BIT 2,B 289 | 0184 CB51 00288 BIT 2,C 290 | 0186 CB52 00289 BIT 2,D 291 | 0188 CB53 00290 BIT 2,E 292 | 018A CB54 00291 BIT 2,H 293 | 018C CB55 00292 BIT 2,L 294 | 018E CB56 00293 BIT 2,(HL) 295 | 0190 CB57 00294 BIT 2,A 296 | 0192 CB58 00295 BIT 3,B 297 | 0194 CB59 00296 BIT 3,C 298 | 0196 CB5A 00297 BIT 3,D 299 | 0198 CB5B 00298 BIT 3,E 300 | 019A CB5C 00299 BIT 3,H 301 | 019C CB5D 00300 BIT 3,L 302 | 019E CB5E 00301 BIT 3,(HL) 303 | 01A0 CB5F 00302 BIT 3,A 304 | 01A2 CB60 00303 BIT 4,B 305 | 01A4 CB61 00304 BIT 4,C 306 | 01A6 CB62 00305 BIT 4,D 307 | 01A8 CB63 00306 BIT 4,E 308 | 01AA CB64 00307 BIT 4,H 309 | 01AC CB65 00308 BIT 4,L 310 | 01AE CB66 00309 BIT 4,(HL) 311 | 01B0 CB67 00310 BIT 4,A 312 | 01B2 CB68 00311 BIT 5,B 313 | 01B4 CB69 00312 BIT 5,C 314 | 01B6 CB6A 00313 BIT 5,D 315 | 01B8 CB6B 00314 BIT 5,E 316 | 01BA CB6C 00315 BIT 5,H 317 | 01BC CB6D 00316 BIT 5,L 318 | 01BE CB6E 00317 BIT 5,(HL) 319 | 01C0 CB6F 00318 BIT 5,A 320 | 01C2 CB70 00319 BIT 6,B 321 | 01C4 CB71 00320 BIT 6,C 322 | 01C6 CB72 00321 BIT 6,D 323 | 01C8 CB73 00322 BIT 6,E 324 | 01CA CB74 00323 BIT 6,H 325 | 01CC CB75 00324 BIT 6,L 326 | 01CE CB76 00325 BIT 6,(HL) 327 | 01D0 CB77 00326 BIT 6,A 328 | 01D2 CB78 00327 BIT 7,B 329 | 01D4 CB79 00328 BIT 7,C 330 | 01D6 CB7A 00329 BIT 7,D 331 | 01D8 CB7B 00330 BIT 7,E 332 | 01DA CB7C 00331 BIT 7,H 333 | 01DC CB7D 00332 BIT 7,L 334 | 01DE CB7E 00333 BIT 7,(HL) 335 | 01E0 CB7F 00334 BIT 7,A 336 | 01E2 CB80 00335 RES 0,B 337 | 01E4 CB81 00336 RES 0,C 338 | 01E6 CB82 00337 RES 0,D 339 | 01E8 CB83 00338 RES 0,E 340 | 01EA CB84 00339 RES 0,H 341 | 01EC CB85 00340 RES 0,L 342 | 01EE CB86 00341 RES 0,(HL) 343 | 01F0 CB87 00342 RES 0,A 344 | 01F2 CB88 00343 RES 1,B 345 | 01F4 CB89 00344 RES 1,C 346 | 01F6 CB8A 00345 RES 1,D 347 | 01F8 CB8B 00346 RES 1,E 348 | 01FA CB8C 00347 RES 1,H 349 | 01FC CB8D 00348 RES 1,L 350 | 01FE CB8E 00349 RES 1,(HL) 351 | 0200 CB8F 00350 RES 1,A 352 | 0202 CB90 00351 RES 2,B 353 | 0204 CB91 00352 RES 2,C 354 | 0206 CB92 00353 RES 2,D 355 | 0208 CB93 00354 RES 2,E 356 | 020A CB94 00355 RES 2,H 357 | 020C CB95 00356 RES 2,L 358 | 020E CB96 00357 RES 2,(HL) 359 | 0210 CB97 00358 RES 2,A 360 | 0212 CB98 00359 RES 3,B 361 | 0214 CB99 00360 RES 3,C 362 | 0216 CB9A 00361 RES 3,D 363 | 0218 CB9B 00362 RES 3,E 364 | 021A CB9C 00363 RES 3,H 365 | 021C CB9D 00364 RES 3,L 366 | 021E CB9E 00365 RES 3,(HL) 367 | 0220 CB9F 00366 RES 3,A 368 | 0222 CBA0 00367 RES 4,B 369 | 0224 CBA1 00368 RES 4,C 370 | 0226 CBA2 00369 RES 4,D 371 | 0228 CBA3 00370 RES 4,E 372 | 022A CBA4 00371 RES 4,H 373 | 022C CBA5 00372 RES 4,L 374 | 022E CBA6 00373 RES 4,(HL) 375 | 0230 CBA7 00374 RES 4,A 376 | 0232 CBA8 00375 RES 5,B 377 | 0234 CBA9 00376 RES 5,C 378 | 0236 CBAA 00377 RES 5,D 379 | 0238 CBAB 00378 RES 5,E 380 | 023A CBAC 00379 RES 5,H 381 | 023C CBAD 00380 RES 5,L 382 | 023E CBAE 00381 RES 5,(HL) 383 | 0240 CBAF 00382 RES 5,A 384 | 0242 CBB0 00383 RES 6,B 385 | 0244 CBB1 00384 RES 6,C 386 | 0246 CBB2 00385 RES 6,D 387 | 0248 CBB3 00386 RES 6,E 388 | 024A CBB4 00387 RES 6,H 389 | 024C CBB5 00388 RES 6,L 390 | 024E CBB6 00389 RES 6,(HL) 391 | 0250 CBB7 00390 RES 6,A 392 | 0252 CBB8 00391 RES 7,B 393 | 0254 CBB9 00392 RES 7,C 394 | 0256 CBBA 00393 RES 7,D 395 | 0258 CBBB 00394 RES 7,E 396 | 025A CBBC 00395 RES 7,H 397 | 025C CBBD 00396 RES 7,L 398 | 025E CBBE 00397 RES 7,(HL) 399 | 0260 CBBF 00398 RES 7,A 400 | 0262 CBC0 00399 SET 0,B 401 | 0264 CBC1 00400 SET 0,C 402 | 0266 CBC2 00401 SET 0,D 403 | 0268 CBC3 00402 SET 0,E 404 | 026A CBC4 00403 SET 0,H 405 | 026C CBC5 00404 SET 0,L 406 | 026E CBC6 00405 SET 0,(HL) 407 | 0270 CBC7 00406 SET 0,A 408 | 0272 CBC8 00407 SET 1,B 409 | 0274 CBC9 00408 SET 1,C 410 | 0276 CBCA 00409 SET 1,D 411 | 0278 CBCB 00410 SET 1,E 412 | 027A CBCC 00411 SET 1,H 413 | 027C CBCD 00412 SET 1,L 414 | 027E CBCE 00413 SET 1,(HL) 415 | 0280 CBCF 00414 SET 1,A 416 | 0282 CBD0 00415 SET 2,B 417 | 0284 CBD1 00416 SET 2,C 418 | 0286 CBD2 00417 SET 2,D 419 | 0288 CBD3 00418 SET 2,E 420 | 028A CBD4 00419 SET 2,H 421 | 028C CBD5 00420 SET 2,L 422 | 028E CBD6 00421 SET 2,(HL) 423 | 0290 CBD7 00422 SET 2,A 424 | 0292 CBD8 00423 SET 3,B 425 | 0294 CBD9 00424 SET 3,C 426 | 0296 CBDA 00425 SET 3,D 427 | 0298 CBDB 00426 SET 3,E 428 | 029A CBDC 00427 SET 3,H 429 | 029C CBDD 00428 SET 3,L 430 | 029E CBDE 00429 SET 3,(HL) 431 | 02A0 CBDF 00430 SET 3,A 432 | 02A2 CBE0 00431 SET 4,B 433 | 02A4 CBE1 00432 SET 4,C 434 | 02A6 CBE2 00433 SET 4,D 435 | 02A8 CBE3 00434 SET 4,E 436 | 02AA CBE4 00435 SET 4,H 437 | 02AC CBE5 00436 SET 4,L 438 | 02AE CBE6 00437 SET 4,(HL) 439 | 02B0 CBE7 00438 SET 4,A 440 | 02B2 CBE8 00439 SET 5,B 441 | 02B4 CBE9 00440 SET 5,C 442 | 02B6 CBEA 00441 SET 5,D 443 | 02B8 CBEB 00442 SET 5,E 444 | 02BA CBEC 00443 SET 5,H 445 | 02BC CBED 00444 SET 5,L 446 | 02BE CBEE 00445 SET 5,(HL) 447 | 02C0 CBEF 00446 SET 5,A 448 | 02C2 CBF0 00447 SET 6,B 449 | 02C4 CBF1 00448 SET 6,C 450 | 02C6 CBF2 00449 SET 6,D 451 | 02C8 CBF3 00450 SET 6,E 452 | 02CA CBF4 00451 SET 6,H 453 | 02CC CBF5 00452 SET 6,L 454 | 02CE CBF6 00453 SET 6,(HL) 455 | 02D0 CBF7 00454 SET 6,A 456 | 02D2 CBF8 00455 SET 7,B 457 | 02D4 CBF9 00456 SET 7,C 458 | 02D6 CBFA 00457 SET 7,D 459 | 02D8 CBFB 00458 SET 7,E 460 | 02DA CBFC 00459 SET 7,H 461 | 02DC CBFD 00460 SET 7,L 462 | 02DE CBFE 00461 SET 7,(HL) 463 | 02E0 CBFF 00462 SET 7,A 464 | 02E2 CCBBAA 00463 CALL Z,$AABB 465 | 02E5 CDBBAA 00464 CALL $AABB 466 | 02E8 CE55 00465 ADC A,$55 467 | 02EA CF 00466 RST 8 468 | 02EB D0 00467 RET NC 469 | 02EC D1 00468 POP DE 470 | 02ED D2BBAA 00469 JP NC,$AABB 471 | 02F0 D355 00470 OUT ($55),A 472 | 02F2 D4BBAA 00471 CALL NC,$AABB 473 | 02F5 D5 00472 PUSH DE 474 | 02F6 D655 00473 SUB $55 475 | 02F8 D7 00474 RST 16 476 | 02F9 D8 00475 RET C 477 | 02FA D9 00476 EXX 478 | 02FB DABBAA 00477 JP C,$AABB 479 | 02FE DB55 00478 IN A,($55) 480 | 0300 DCBBAA 00479 CALL C,$AABB 481 | 0303 DD09 00480 ADD IX,BC 482 | 0305 DD19 00481 ADD IX,DE 483 | 0307 DD21BBAA 00482 LD IX,$AABB 484 | 030B DD22BBAA 00483 LD ($AABB),IX 485 | 030F DD23 00484 INC IX 486 | 0311 DD29 00485 ADD IX,IX 487 | 0313 DD2ABBAA 00486 LD IX,($AABB) 488 | 0317 DD2B 00487 DEC IX 489 | 0319 DD3405 00488 INC (IX+5) 490 | 031C DD3505 00489 DEC (IX+5) 491 | 031F DD3605BB 00490 LD (IX+5),$BB 492 | 0323 DD39 00491 ADD IX,SP 493 | 0325 DD4605 00492 LD B,(IX+5) 494 | 0328 DD4E05 00493 LD C,(IX+5) 495 | 032B DD5605 00494 LD D,(IX+5) 496 | 032E DD5E05 00495 LD E,(IX+5) 497 | 0331 DD6605 00496 LD H,(IX+5) 498 | 0334 DD6E05 00497 LD L,(IX+5) 499 | 0337 DD7005 00498 LD (IX+5),B 500 | 033A DD7105 00499 LD (IX+5),C 501 | 033D DD7205 00500 LD (IX+5),D 502 | 0340 DD7305 00501 LD (IX+5),E 503 | 0343 DD7405 00502 LD (IX+5),H 504 | 0346 DD7505 00503 LD (IX+5),L 505 | 0349 DD7705 00504 LD (IX+5),A 506 | 034C DD7E05 00505 LD A,(IX+5) 507 | 034F DD8605 00506 ADD A,(IX+5) 508 | 0352 DD8E05 00507 ADC A,(IX+5) 509 | 0355 DD9605 00508 SUB (IX+5) 510 | 0358 DD9E05 00509 SBC A,(IX+5) 511 | 035B DDA605 00510 AND (IX+5) 512 | 035E DDAE05 00511 XOR (IX+5) 513 | 0361 DDB605 00512 OR (IX+5) 514 | 0364 DDBE05 00513 CP (IX+5) 515 | 0367 DDCB0506 00514 RLC (IX+5) 516 | 036B DDCB050E 00515 RRC (IX+5) 517 | 036F DDCB0516 00516 RL (IX+5) 518 | 0373 DDCB051E 00517 RR (IX+5) 519 | 0377 DDCB0526 00518 SLA (IX+5) 520 | 037B DDCB052E 00519 SRA (IX+5) 521 | 037F DDCB053E 00520 SRL (IX+5) 522 | 0383 DDCB0546 00521 BIT 0,(IX+5) 523 | 0387 DDCB057E 00522 BIT 7,(IX+5) 524 | 038B DDCB0586 00523 RES 0,(IX+5) 525 | 038F DDCB05BE 00524 RES 7,(IX+5) 526 | 0393 DDCB05C6 00525 SET 0,(IX+5) 527 | 0397 DDCB05FE 00526 SET 7,(IX+5) 528 | 039B DDE1 00527 POP IX 529 | 039D DDE3 00528 EX (SP),IX 530 | 039F DDE5 00529 PUSH IX 531 | 03A1 DDE9 00530 JP (IX) 532 | 03A3 DDF9 00531 LD SP,IX 533 | 03A5 DE55 00532 SBC A,$55 534 | 03A7 DF 00533 RST 24 535 | 03A8 E0 00534 RET PO 536 | 03A9 E1 00535 POP HL 537 | 03AA E2BBAA 00536 JP PO,$AABB 538 | 03AD E3 00537 EX (SP),HL 539 | 03AE E4BBAA 00538 CALL PO,$AABB 540 | 03B1 E5 00539 PUSH HL 541 | 03B2 E655 00540 AND $55 542 | 03B4 E7 00541 RST 32 543 | 03B5 E8 00542 RET PE 544 | 03B6 E9 00543 JP (HL) 545 | 03B7 EABBAA 00544 JP PE,$AABB 546 | 03BA EB 00545 EX DE,HL 547 | 03BB ECBBAA 00546 CALL PE,$AABB 548 | 03BE ED40 00547 IN B,(C) 549 | 03C0 ED41 00548 OUT (C),B 550 | 03C2 ED42 00549 SBC HL,BC 551 | 03C4 ED43BBAA 00550 LD ($AABB),BC 552 | 03C8 ED44 00551 NEG 553 | 03CA ED45 00552 RETN 554 | 03CC ED46 00553 IM 0 555 | 03CE ED47 00554 LD I,A 556 | 03D0 ED48 00555 IN C,(C) 557 | 03D2 ED49 00556 OUT (C),C 558 | 03D4 ED4A 00557 ADC HL,BC 559 | 03D6 ED4BBBAA 00558 LD BC,($AABB) 560 | 03DA ED4D 00559 RETI 561 | 03DC ED4F 00560 LD R,A 562 | 03DE ED50 00561 IN D,(C) 563 | 03E0 ED51 00562 OUT (C),D 564 | 03E2 ED52 00563 SBC HL,DE 565 | 03E4 ED53BBAA 00564 LD ($AABB),DE 566 | 03E8 ED56 00565 IM 1 567 | 03EA ED57 00566 LD A,I 568 | 03EC ED58 00567 IN E,(C) 569 | 03EE ED59 00568 OUT (C),E 570 | 03F0 ED5A 00569 ADC HL,DE 571 | 03F2 ED5BBBAA 00570 LD DE,($AABB) 572 | 03F6 ED5E 00571 IM 2 573 | 03F8 ED5F 00572 LD A,R 574 | 03FA ED62 00573 SBC HL,HL 575 | 03FC ED67 00574 RRD 576 | 03FE ED6A 00575 ADC HL,HL 577 | 0400 ED6F 00576 RLD 578 | 0402 ED72 00577 SBC HL,SP 579 | 0404 ED73BBAA 00578 LD ($AABB),SP 580 | 0408 ED7A 00579 ADC HL,SP 581 | 040A ED7BBBAA 00580 LD SP,($AABB) 582 | 040E EDA0 00581 LDI 583 | 0410 EDA1 00582 CPI 584 | 0412 EDA2 00583 INI 585 | 0414 EDA3 00584 OUTI 586 | 0416 EDA8 00585 LDD 587 | 0418 EDA9 00586 CPD 588 | 041A EDAA 00587 IND 589 | 041C EDAB 00588 OUTD 590 | 041E EDB0 00589 LDIR 591 | 0420 EDB1 00590 CPIR 592 | 0422 EDB2 00591 INIR 593 | 0424 EDB3 00592 OTIR 594 | 0426 EDB8 00593 LDDR 595 | 0428 EDB9 00594 CPDR 596 | 042A EDBA 00595 INDR 597 | 042C EDBB 00596 OTDR 598 | 042E EE55 00597 XOR $55 599 | 0430 EF 00598 RST 40 600 | 0431 F0 00599 RET P 601 | 0432 F1 00600 POP AF 602 | 0433 F2BBAA 00601 JP P,$AABB 603 | 0436 F3 00602 DI 604 | 0437 F4BBAA 00603 CALL P,$AABB 605 | 043A F5 00604 PUSH AF 606 | 043B F655 00605 OR $55 607 | 043D F7 00606 RST $30 608 | 043E F8 00607 RET M 609 | 043F F9 00608 LD SP,HL 610 | 0440 FABBAA 00609 JP M,$AABB 611 | 0443 FB 00610 EI 612 | 0444 FCBBAA 00611 CALL M,$AABB 613 | 0447 FD09 00612 ADD IY,BC 614 | 0449 FD19 00613 ADD IY,DE 615 | 044B FD21BBAA 00614 LD IY,$AABB 616 | 044F FD22BBAA 00615 LD ($AABB),IY 617 | 0453 FD23 00616 INC IY 618 | 0455 FD29 00617 ADD IY,IY 619 | 0457 FD2ABBAA 00618 LD IY,($AABB) 620 | 045B FD2B 00619 DEC IY 621 | 045D FD3405 00620 INC (IY+5) 622 | 0460 FD3505 00621 DEC (IY+5) 623 | 0463 FD3605BB 00622 LD (IY+5),$BB 624 | 0467 FD39 00623 ADD IY,SP 625 | 0469 FD4605 00624 LD B,(IY+5) 626 | 046C FD4E05 00625 LD C,(IY+5) 627 | 046F FD5605 00626 LD D,(IY+5) 628 | 0472 FD5E05 00627 LD E,(IY+5) 629 | 0475 FD6605 00628 LD H,(IY+5) 630 | 0478 FD6E05 00629 LD L,(IY+5) 631 | 047B FD7005 00630 LD (IY+5),B 632 | 047E FD7105 00631 LD (IY+5),C 633 | 0481 FD7205 00632 LD (IY+5),D 634 | 0484 FD7305 00633 LD (IY+5),E 635 | 0487 FD7405 00634 LD (IY+5),H 636 | 048A FD7505 00635 LD (IY+5),L 637 | 048D FD7705 00636 LD (IY+5),A 638 | 0490 FD7E05 00637 LD A,(IY+5) 639 | 0493 FD8605 00638 ADD A,(IY+5) 640 | 0496 FD8E05 00639 ADC A,(IY+5) 641 | 0499 FD9605 00640 SUB (IY+5) 642 | 049C FD9E05 00641 SBC A,(IY+5) 643 | 049F FDA605 00642 AND (IY+5) 644 | 04A2 FDAE05 00643 XOR (IY+5) 645 | 04A5 FDB605 00644 OR (IY+5) 646 | 04A8 FDBE05 00645 CP (IY+5) 647 | 04AB FDCB0506 00646 RLC (IY+5) 648 | 04AF FDCB050E 00647 RRC (IY+5) 649 | 04B3 FDCB0516 00648 RL (IY+5) 650 | 04B7 FDCB051E 00649 RR (IY+5) 651 | 04BB FDCB0526 00650 SLA (IY+5) 652 | 04BF FDCB052E 00651 SRA (IY+5) 653 | 04C3 FDCB053E 00652 SRL (IY+5) 654 | 04C7 FDCB0546 00653 BIT 0,(IY+5) 655 | 04CB FDCB057E 00654 BIT 7,(IY+5) 656 | 04CF FDCB0586 00655 RES 0,(IY+5) 657 | 04D3 FDCB05BE 00656 RES 7,(IY+5) 658 | 04D7 FDCB05C6 00657 SET 0,(IY+5) 659 | 04DB FDCB05FE 00658 SET 7,(IY+5) 660 | 04DF FDE1 00659 POP IY 661 | 04E1 FDE3 00660 EX (SP),IY 662 | 04E3 FDE5 00661 PUSH IY 663 | 04E5 FDE9 00662 JP (IY) 664 | 04E7 FDF9 00663 LD SP,IY 665 | 04E9 FE55 00664 CP $55 666 | 04EB FF 00665 RST $38 667 | 04EC 00666 668 | 04EC 00667 ; Undocumented instructions 669 | 04EC DD24 00668 INC IXH 670 | 04EE DD25 00669 DEC IXH 671 | 04F0 DD2655 00670 LD IXH,$55 672 | 04F3 DD2C 00671 INC IXL 673 | 04F5 DD2D 00672 DEC IXL 674 | 04F7 DD2E55 00673 LD IXL,$55 675 | 04FA DD44 00674 LD B,IXH 676 | 04FC DD45 00675 LD B,IXL 677 | 04FE DD4C 00676 LD C,IXH 678 | 0500 DD4D 00677 LD C,IXL 679 | 0502 DD54 00678 LD D,IXH 680 | 0504 DD55 00679 LD D,IXL 681 | 0506 DD5C 00680 LD E,IXH 682 | 0508 DD5D 00681 LD E,IXL 683 | 050A DD60 00682 LD IXH,B 684 | 050C DD61 00683 LD IXH,C 685 | 050E DD62 00684 LD IXH,D 686 | 0510 DD63 00685 LD IXH,E 687 | 0512 DD64 00686 LD IXH,IXH 688 | 0514 DD65 00687 LD IXH,IXL 689 | 0516 DD67 00688 LD IXH,A 690 | 0518 DD68 00689 LD IXL,B 691 | 051A DD69 00690 LD IXL,C 692 | 051C DD6A 00691 LD IXL,D 693 | 051E DD6B 00692 LD IXL,E 694 | 0520 DD6C 00693 LD IXL,IXH 695 | 0522 DD6D 00694 LD IXL,IXL 696 | 0524 DD6F 00695 LD IXL,A 697 | 0526 DD7C 00696 LD A,IXH 698 | 0528 DD7D 00697 LD A,IXL 699 | 052A DD84 00698 ADD A,IXH 700 | 052C DD85 00699 ADD A,IXL 701 | 052E DD8C 00700 ADC A,IXH 702 | 0530 DD8D 00701 ADC A,IXL 703 | 0532 DD94 00702 SUB IXH 704 | 0534 DD95 00703 SUB IXL 705 | 0536 DD9C 00704 SBC A,IXH 706 | 0538 DD9D 00705 SBC A,IXL 707 | 053A DDA4 00706 AND IXH 708 | 053C DDA5 00707 AND IXL 709 | 053E DDAC 00708 XOR IXH 710 | 0540 DDAD 00709 XOR IXL 711 | 0542 DDB4 00710 OR IXH 712 | 0544 DDB5 00711 OR IXL 713 | 0546 DDBC 00712 CP IXH 714 | 0548 DDBD 00713 CP IXL 715 | 054A 00714 716 | 054A FD24 00715 INC IYH 717 | 054C FD25 00716 DEC IYH 718 | 054E FD2655 00717 LD IYH,$55 719 | 0551 FD2C 00718 INC IYL 720 | 0553 FD2D 00719 DEC IYL 721 | 0555 FD2E55 00720 LD IYL,$55 722 | 0558 FD44 00721 LD B,IYH 723 | 055A FD45 00722 LD B,IYL 724 | 055C FD4C 00723 LD C,IYH 725 | 055E FD4D 00724 LD C,IYL 726 | 0560 FD54 00725 LD D,IYH 727 | 0562 FD55 00726 LD D,IYL 728 | 0564 FD5C 00727 LD E,IYH 729 | 0566 FD5D 00728 LD E,IYL 730 | 0568 FD60 00729 LD IYH,B 731 | 056A FD61 00730 LD IYH,C 732 | 056C FD62 00731 LD IYH,D 733 | 056E FD63 00732 LD IYH,E 734 | 0570 FD64 00733 LD IYH,IYH 735 | 0572 FD65 00734 LD IYH,IYL 736 | 0574 FD67 00735 LD IYH,A 737 | 0576 FD68 00736 LD IYL,B 738 | 0578 FD69 00737 LD IYL,C 739 | 057A FD6A 00738 LD IYL,D 740 | 057C FD6B 00739 LD IYL,E 741 | 057E FD6C 00740 LD IYL,IYH 742 | 0580 FD6D 00741 LD IYL,IYL 743 | 0582 FD6F 00742 LD IYL,A 744 | 0584 FD7C 00743 LD A,IYH 745 | 0586 FD7D 00744 LD A,IYL 746 | 0588 FD84 00745 ADD A,IYH 747 | 058A FD85 00746 ADD A,IYL 748 | 058C FD8C 00747 ADC A,IYH 749 | 058E FD8D 00748 ADC A,IYL 750 | 0590 FD94 00749 SUB IYH 751 | 0592 FD95 00750 SUB IYL 752 | 0594 FD9C 00751 SBC A,IYH 753 | 0596 FD9D 00752 SBC A,IYL 754 | 0598 FDA4 00753 AND IYH 755 | 059A FDA5 00754 AND IYL 756 | 059C FDAC 00755 XOR IYH 757 | 059E FDAD 00756 XOR IYL 758 | 05A0 FDB4 00757 OR IYH 759 | 05A2 FDB5 00758 OR IYL 760 | 05A4 FDBC 00759 CP IYH 761 | 05A6 FDBD 00760 CP IYL 762 | 05A8 CB30 00761 SLL B 763 | 05AA CB31 00762 SLL C 764 | 05AC CB32 00763 SLL D 765 | 05AE CB33 00764 SLL E 766 | 05B0 CB34 00765 SLL H 767 | 05B2 CB35 00766 SLL L 768 | 05B4 CB36 00767 SLL (HL) 769 | 05B6 CB37 00768 SLL A 770 | 771 | 00000 ERRORS FOUND 772 | 00000 WARNINGS FOUND 773 | 774 | 01464 PROGRAM BYTES 775 | 776 | -------------------------------------------------------------------------------- /gasm80.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Generic Assembler Z80 (gasm80) 3 | ** 4 | ** by Oscar Toledo G. 5 | ** https://nanochess.org/ 6 | ** 7 | ** Creation date: Mar/03/2024. Based on tinyasm. Fully functional. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /*#define DEBUG*/ 17 | 18 | char *input_filename; 19 | int line_number; 20 | 21 | char *output_filename; 22 | FILE *output; 23 | int output_address; 24 | 25 | char *listing_filename; 26 | FILE *listing; 27 | 28 | char *symbol_filename; 29 | FILE *symbol; 30 | 31 | enum {CPU_Z80, CPU_6502} processor; 32 | int assembler_step; 33 | int default_start_address; 34 | int start_address; 35 | int address; 36 | int first_time; 37 | 38 | int instruction_offset; 39 | 40 | int instruction_register; 41 | int instruction_register_2; 42 | 43 | int instruction_value; 44 | int instruction_value2; 45 | 46 | #define MAX_SIZE 4096 47 | 48 | char line[MAX_SIZE]; 49 | char part[MAX_SIZE]; 50 | char name[MAX_SIZE]; 51 | char expr_name[MAX_SIZE]; 52 | char undefined_name[MAX_SIZE]; 53 | char global_label[MAX_SIZE]; 54 | char included_file[MAX_SIZE]; 55 | char *prev_p; 56 | char *p; 57 | 58 | char *g; 59 | char generated[8]; 60 | 61 | int errors; 62 | int warnings; 63 | int bytes; 64 | int change; 65 | int change_number; 66 | 67 | struct label { 68 | struct label *left; 69 | struct label *right; 70 | int value; 71 | char name[1]; 72 | }; 73 | 74 | struct label *label_list; 75 | struct label *last_label; 76 | int undefined; 77 | 78 | /* 79 | ** For 6502, the jump instructions .L are automatically expanded as needed 80 | ** (saves a ton of bytes along CVBasic) 81 | */ 82 | struct extend_jump { 83 | struct extend_jump *next; 84 | int address; 85 | int target; 86 | int relative; 87 | }; 88 | 89 | struct extend_jump *first_jump; 90 | struct extend_jump *current_jump; 91 | struct extend_jump *last_jump; 92 | int building_jumps; 93 | 94 | /* 95 | ** Instructions using less bytes should appear first. 96 | */ 97 | char *cpu_6502_instruction_set[] = { 98 | /* 99 | ** Undocumented instructions. 100 | ** Info from: https://www.masswerk.at/nowgobang/2021/6502-illegal-opcodes 101 | */ 102 | "SLO", "(%i8,X)", "x03 %i8", 103 | "SLO", "(%i8),Y", "x13 %i8", 104 | "RLA", "(%i8,X)", "x23 %i8", 105 | "RLA", "(%i8),Y", "x33 %i8", 106 | "SRE", "(%i8,X)", "x43 %i8", 107 | "SRE", "(%i8),Y", "x53 %i8", 108 | "RRA", "(%i8,X)", "x63 %i8", 109 | "RRA", "(%i8),Y", "x73 %i8", 110 | "SAX", "(%i8,X)", "x83 %i8", 111 | "SHA", "(%i8),Y", "x93 %i8", 112 | "LAX", "(%i8,X)", "xa3 %i8", 113 | "LAX", "(%i8),Y", "xb3 %i8", 114 | "DCP", "(%i8,X)", "xc3 %i8", 115 | "DCP", "(%i8),Y", "xd3 %i8", 116 | "ISC", "(%i8,X)", "xe3 %i8", 117 | "ISC", "(%i8),Y", "xf3 %i8", 118 | "SLO", "%i8", "x07 %i8", 119 | "SLO", "%i8,X", "x17 %i8", 120 | "RLA", "%i8", "x27 %i8", 121 | "RLA", "%i8,X", "x37 %i8", 122 | "SRE", "%i8", "x47 %i8", 123 | "SRE", "%i8,X", "x57 %i8", 124 | "RRA", "%i8", "x67 %i8", 125 | "RRA", "%i8,X", "x77 %i8", 126 | "SAX", "%i8", "x87 %i8", 127 | "SAX", "%i8,Y", "x97 %i8", 128 | "LAX", "%i8", "xa7 %i8", 129 | "LAX", "%i8,Y", "xb7 %i8", 130 | "DCP", "%i8", "xc7 %i8", 131 | "DCP", "%i8,X", "xd7 %i8", 132 | "ISC", "%i8", "xe7 %i8", 133 | "ISC", "%i8,X", "xf7 %i8", 134 | "ANC", "#%i8", "x0b %i8", 135 | "ALR", "#%i8", "x4b %i8", 136 | "ARR", "#%i8", "x6b %i8", 137 | "ANE", "#%i8", "x8b %i8", 138 | "LXA", "#%i8", "xab %i8", 139 | "SBX", "#%i8", "xcb %i8", 140 | "USBC", "#%i8", "xeb %i8", 141 | "SLO", "%i16,Y", "x1b %i16", 142 | "RLA", "%i16,Y", "x3b %i16", 143 | "SRE", "%i16,Y", "x5b %i16", 144 | "RRA", "%i16,Y", "x7b %i16", 145 | "TAS", "%i16,Y", "x9b %i16", 146 | "LAS", "%i16,Y", "xbb %i16", 147 | "DCP", "%i16,Y", "xdb %i16", 148 | "ISC", "%i16,Y", "xfb %i16", 149 | "SHY", "%i16,X", "x9c %i16", 150 | "SHX", "%i16,Y", "x9e %i16", 151 | "SLO", "%i16", "x0f %i16", 152 | "SLO", "%i16,X", "x1f %i16", 153 | "RLA", "%i16", "x2f %i16", 154 | "RLA", "%i16,X", "x3f %i16", 155 | "SRE", "%i16", "x4f %i16", 156 | "SRE", "%i16,X", "x5f %i16", 157 | "RRA", "%i16", "x6f %i16", 158 | "RRA", "%i16,X", "x7f %i16", 159 | "SAX", "%i16", "x8f %i16", 160 | "SHA", "%i16,Y", "x9f %i16", 161 | "LAX", "%i16", "xaf %i16", 162 | "LAX", "%i16,Y", "xbf %i16", 163 | "DCP", "%i16", "xcf %i16", 164 | "DCP", "%i16,X", "xdf %i16", 165 | "ISC", "%i16", "xef %i16", 166 | "ISC", "%i16,X", "xff %i16", 167 | "SLO.W", "%i16", "x0f %i16", 168 | "SLO.W", "%i16,X", "x1f %i16", 169 | "RLA.W", "%i16", "x2f %i16", 170 | "RLA.W", "%i16,X", "x3f %i16", 171 | "SRE.W", "%i16", "x4f %i16", 172 | "SRE.W", "%i16,X", "x5f %i16", 173 | "RRA.W", "%i16", "x6f %i16", 174 | "RRA.W", "%i16,X", "x7f %i16", 175 | "SAX.W", "%i16", "x8f %i16", 176 | "SHA.W", "%i16,Y", "x9f %i16", 177 | "LAX.W", "%i16", "xaf %i16", 178 | "LAX.W", "%i16,Y", "xbf %i16", 179 | "DCP.W", "%i16", "xcf %i16", 180 | "DCP.W", "%i16,X", "xdf %i16", 181 | "ISC.W", "%i16", "xef %i16", 182 | "ISC.W", "%i16,X", "xff %i16", 183 | /* Standard instruction set */ 184 | "LDY", "#%i8", "xa0 %i8", 185 | "LDX", "#%i8", "xa2 %i8", 186 | "CPY", "#%i8", "xc0 %i8", 187 | "CPX", "#%i8", "xe0 %i8", 188 | "ORA", "#%i8", "x09 %i8", 189 | "AND", "#%i8", "x29 %i8", 190 | "EOR", "#%i8", "x49 %i8", 191 | "ADC", "#%i8", "x69 %i8", 192 | "LDA", "#%i8", "xa9 %i8", 193 | "CMP", "#%i8", "xc9 %i8", 194 | "SBC", "#%i8", "xe9 %i8", 195 | "BPL", "%a8", "x10 %a8", 196 | "BMI", "%a8", "x30 %a8", 197 | "BCC", "%a8", "x90 %a8", 198 | "BCS", "%a8", "xb0 %a8", 199 | "BNE", "%a8", "xd0 %a8", 200 | "BEQ", "%a8", "xf0 %a8", 201 | "BVC", "%a8", "x50 %a8", 202 | "BVS", "%a8", "x70 %a8", 203 | "BPL.L", "%i16", "x10 %a16", 204 | "BMI.L", "%i16", "x30 %a16", 205 | "BCC.L", "%i16", "x90 %a16", 206 | "BCS.L", "%i16", "xb0 %a16", 207 | "BNE.L", "%i16", "xd0 %a16", 208 | "BEQ.L", "%i16", "xf0 %a16", 209 | "BVC.L", "%i16", "x50 %a16", 210 | "BVS.L", "%i16", "x70 %a16", 211 | "BRX", "", "x00", 212 | "JSR", "%i16", "x20 %i16", 213 | "RTI", "", "x40", 214 | "RTS", "", "x60", 215 | "ORA", "(%i8,X)", "x01 %i8", 216 | "ORA", "(%i8),Y", "x11 %i8", 217 | "AND", "(%i8,X)", "x21 %i8", 218 | "AND", "(%i8),Y", "x31 %i8", 219 | "EOR", "(%i8,X)", "x41 %i8", 220 | "EOR", "(%i8),Y", "x51 %i8", 221 | "ADC", "(%i8,X)", "x61 %i8", 222 | "ADC", "(%i8),Y", "x71 %i8", 223 | "STA", "(%i8,X)", "x81 %i8", 224 | "STA", "(%i8),Y", "x91 %i8", 225 | "LDA", "(%i8,X)", "xa1 %i8", 226 | "LDA", "(%i8),Y", "xb1 %i8", 227 | "CMP", "(%i8,X)", "xc1 %i8", 228 | "CMP", "(%i8),Y", "xd1 %i8", 229 | "SBC", "(%i8,X)", "xe1 %i8", 230 | "SBC", "(%i8),Y", "xf1 %i8", 231 | "BIT", "%i8", "x24 %i8", 232 | "STY", "%i8", "x84 %i8", 233 | "STY", "%i8,X", "x94 %i8", 234 | "LDY", "%i8", "xa4 %i8", 235 | "LDY", "%i8,X", "xb4 %i8", 236 | "CPY", "%i8", "xc4 %i8", 237 | "CPX", "%i8", "xe4 %i8", 238 | "ORA", "%i8", "x05 %i8", 239 | "ORA", "%i8,X", "x15 %i8", 240 | "AND", "%i8", "x25 %i8", 241 | "AND", "%i8,X", "x35 %i8", 242 | "EOR", "%i8", "x45 %i8", 243 | "EOR", "%i8,X", "x55 %i8", 244 | "ADC", "%i8", "x65 %i8", 245 | "ADC", "%i8,X", "x75 %i8", 246 | "STA", "%i8", "x85 %i8", 247 | "STA", "%i8,X", "x95 %i8", 248 | "LDA", "%i8", "xa5 %i8", 249 | "LDA", "%i8,X", "xb5 %i8", 250 | "CMP", "%i8", "xc5 %i8", 251 | "CMP", "%i8,X", "xd5 %i8", 252 | "SBC", "%i8", "xe5 %i8", 253 | "SBC", "%i8,X", "xf5 %i8", 254 | "ASL", "%i8", "x06 %i8", 255 | "ASL", "%i8,X", "x16 %i8", 256 | "ROL", "%i8", "x26 %i8", 257 | "ROL", "%i8,X", "x36 %i8", 258 | "LSR", "%i8", "x46 %i8", 259 | "LSR", "%i8,X", "x56 %i8", 260 | "ROR", "%i8", "x66 %i8", 261 | "ROR", "%i8,X", "x76 %i8", 262 | "STX", "%i8", "x86 %i8", 263 | "STX", "%i8,Y", "x96 %i8", 264 | "LDX", "%i8", "xa6 %i8", 265 | "LDX", "%i8,Y", "xb6 %i8", 266 | "DEC", "%i8", "xc6 %i8", 267 | "DEC", "%i8,X", "xd6 %i8", 268 | "INC", "%i8", "xe6 %i8", 269 | "INC", "%i8,X", "xf6 %i8", 270 | "PHP", "", "x08", 271 | "CLC", "", "x18", 272 | "PLP", "", "x28", 273 | "SEC", "", "x38", 274 | "PHA", "", "x48", 275 | "CLI", "", "x58", 276 | "PLA", "", "x68", 277 | "SEI", "", "x78", 278 | "DEY", "", "x88", 279 | "TYA", "", "x98", 280 | "TAY", "", "xa8", 281 | "CLV", "", "xb8", 282 | "INY", "", "xc8", 283 | "CLD", "", "xd8", 284 | "INX", "", "xe8", 285 | "SED", "", "xf8", 286 | "ORA", "%i16,Y", "x19 %i16", 287 | "AND", "%i16,Y", "x39 %i16", 288 | "EOR", "%i16,Y", "x59 %i16", 289 | "ADC", "%i16,Y", "x79 %i16", 290 | "STA", "%i16,Y", "x99 %i16", 291 | "LDA", "%i16,Y", "xb9 %i16", 292 | "CMP", "%i16,Y", "xd9 %i16", 293 | "SBC", "%i16,Y", "xf9 %i16", 294 | "ORA.W", "%i16,Y", "x19 %i16", 295 | "AND.W", "%i16,Y", "x39 %i16", 296 | "EOR.W", "%i16,Y", "x59 %i16", 297 | "ADC.W", "%i16,Y", "x79 %i16", 298 | "STA.W", "%i16,Y", "x99 %i16", 299 | "LDA.W", "%i16,Y", "xb9 %i16", 300 | "CMP.W", "%i16,Y", "xd9 %i16", 301 | "SBC.W", "%i16,Y", "xf9 %i16", 302 | "BIT.W", "%i16", "x2c %i16", 303 | "ASL", "A", "x0a", 304 | "ROL", "A", "x2a", 305 | "LSR", "A", "x4a", 306 | "ROR", "A", "x6a", 307 | "TXA", "", "x8a", 308 | "TXS", "", "x9a", 309 | "TAX", "", "xaa", 310 | "TSX", "", "xba", 311 | "DEX", "", "xca", 312 | "NOP", "", "xea", 313 | "BIT", "%i16", "x2c %i16", 314 | "JMP", "(%i16)", "x6c %i16", 315 | "JMP", "%i16", "x4c %i16", 316 | "STY", "%i16", "x8c %i16", 317 | "LDY", "%i16", "xac %i16", 318 | "LDY", "%i16,X", "xbc %i16", 319 | "CPY", "%i16", "xcc %i16", 320 | "CPX", "%i16", "xec %i16", 321 | "ORA", "%i16", "x0d %i16", 322 | "ORA", "%i16,X", "x1d %i16", 323 | "AND", "%i16", "x2d %i16", 324 | "AND", "%i16,X", "x3d %i16", 325 | "EOR", "%i16", "x4d %i16", 326 | "EOR", "%i16,X", "x5d %i16", 327 | "ADC", "%i16", "x6d %i16", 328 | "ADC", "%i16,X", "x7d %i16", 329 | "STA", "%i16", "x8d %i16", 330 | "STA", "%i16,X", "x9d %i16", 331 | "LDA", "%i16", "xad %i16", 332 | "LDA", "%i16,X", "xbd %i16", 333 | "CMP", "%i16", "xcd %i16", 334 | "CMP", "%i16,X", "xdd %i16", 335 | "SBC", "%i16", "xed %i16", 336 | "SBC", "%i16,X", "xfd %i16", 337 | "ASL", "%i16", "x0e %i16", 338 | "ASL", "%i16,X", "x1e %i16", 339 | "ROL", "%i16", "x2e %i16", 340 | "ROL", "%i16,X", "x3e %i16", 341 | "LSR", "%i16", "x4e %i16", 342 | "LSR", "%i16,X", "x5e %i16", 343 | "ROR", "%i16", "x6e %i16", 344 | "ROR", "%i16,X", "x7e %i16", 345 | "STX", "%i16", "x8e %i16", 346 | "LDX", "%i16", "xae %i16", 347 | "LDX", "%i16,Y", "xbe %i16", 348 | "DEC", "%i16", "xce %i16", 349 | "DEC", "%i16,X", "xde %i16", 350 | "INC", "%i16", "xee %i16", 351 | "INC", "%i16,X", "xfe %i16", 352 | "STY.W", "%i16", "x8c %i16", 353 | "LDY.W", "%i16", "xac %i16", 354 | "LDY.W", "%i16,X", "xbc %i16", 355 | "CPY.W", "%i16", "xcc %i16", 356 | "CPX.W", "%i16", "xec %i16", 357 | "ORA.W", "%i16", "x0d %i16", 358 | "ORA.W", "%i16,X", "x1d %i16", 359 | "AND.W", "%i16", "x2d %i16", 360 | "AND.W", "%i16,X", "x3d %i16", 361 | "EOR.W", "%i16", "x4d %i16", 362 | "EOR.W", "%i16,X", "x5d %i16", 363 | "ADC.W", "%i16", "x6d %i16", 364 | "ADC.W", "%i16,X", "x7d %i16", 365 | "STA.W", "%i16", "x8d %i16", 366 | "STA.W", "%i16,X", "x9d %i16", 367 | "LDA.W", "%i16", "xad %i16", 368 | "LDA.W", "%i16,X", "xbd %i16", 369 | "CMP.W", "%i16", "xcd %i16", 370 | "CMP.W", "%i16,X", "xdd %i16", 371 | "SBC.W", "%i16", "xed %i16", 372 | "SBC.W", "%i16,X", "xfd %i16", 373 | "ASL.W", "%i16", "x0e %i16", 374 | "ASL.W", "%i16,X", "x1e %i16", 375 | "ROL.W", "%i16", "x2e %i16", 376 | "ROL.W", "%i16,X", "x3e %i16", 377 | "LSR.W", "%i16", "x4e %i16", 378 | "LSR.W", "%i16,X", "x5e %i16", 379 | "ROR.W", "%i16", "x6e %i16", 380 | "ROR.W", "%i16,X", "x7e %i16", 381 | "STX.W", "%i16", "x8e %i16", 382 | "LDX.W", "%i16", "xae %i16", 383 | "LDX.W", "%i16,Y", "xbe %i16", 384 | "DEC.W", "%i16", "xce %i16", 385 | "DEC.W", "%i16,X", "xde %i16", 386 | "INC.W", "%i16", "xee %i16", 387 | "INC.W", "%i16,X", "xfe %i16", 388 | NULL, NULL, NULL, 389 | }; 390 | 391 | char *cpu_z80_instruction_set[] = { 392 | "NOP", "", "x00", 393 | "LD", "%t8,(IX%d8)", "xdd b01%t8110 %d8", 394 | "LD", "%t8,(IY%d8)", "xfd b01%t8110 %d8", 395 | "LD", "HL,(%i16)", "x2a %i16", 396 | "LD", "A,(%i16)", "x3a %i16", 397 | "LD", "(IX%d8),%t8", "xdd b01110%t8 %d8", 398 | "LD", "(IY%d8),%t8", "xfd b01110%t8 %d8", 399 | "LD", "(IX%d8),%i8", "xdd b00110110 %d8 %i8", 400 | "LD", "(IY%d8),%i8", "xfd b00110110 %d8 %i8", 401 | "LD", "(BC),A", "x02", 402 | "INC", "%r16", "b00%r160011", 403 | "INC", "%r8", "b00%r8100", 404 | "DEC", "%r8", "b00%r8101", 405 | "DEC", "%r16", "b00%r161011", 406 | "RLCA", "", "x07", 407 | "EX", "AF,AF'", "x08", 408 | "ADD", "HL,%r16", "b00%r161001", 409 | "LD", "A,(BC)", "x0a", 410 | "RRCA", "", "x0f", 411 | "DJNZ", "%a8", "x10 %a8", 412 | "LD", "(DE),A", "x12", 413 | "RLA", "", "x17", 414 | "RRA", "", "x1f", 415 | "JR", "%a8", "x18 %a8", 416 | "LD", "A,(DE)", "x1a", 417 | "JR", "NZ,%a8", "x20 %a8", 418 | "LD", "(%i16),HL", "x22 %i16", 419 | "DAA", "", "x27", 420 | "JR", "Z,%a8", "x28 %a8", 421 | "CPL", "", "x2f", 422 | "JR", "NC,%a8", "x30 %a8", 423 | "LD", "(%i16),A", "x32 %i16", 424 | "SCF", "", "x37", 425 | "JR", "C,%a8", "x38 %a8", 426 | "CCF", "", "x3f", 427 | "HALT", "", "x76", 428 | "RET", "%f", "b11%f000", 429 | "POP", "%s16", "b11%s160001", 430 | "JP", "%f,%i16", "b11%f010 %i16", 431 | "CALL", "%f,%i16", "b11%f100 %i16", 432 | "PUSH", "%s16", "b11%s160101", 433 | "RST", "%b8", "b11%b8111", 434 | "RET", "", "xc9", 435 | "RLC", "%r8", "xcb b00000%r8", 436 | "RRC", "%r8", "xcb b00001%r8", 437 | "RL", "%r8", "xcb b00010%r8", 438 | "RR", "%r8", "xcb b00011%r8", 439 | "SLA", "%r8", "xcb b00100%r8", 440 | "SRA", "%r8", "xcb b00101%r8", 441 | "SLL", "%r8", "xcb b00110%r8", 442 | "SRL", "%r8", "xcb b00111%r8", 443 | "BIT", "%c,%r8", "xcb b01%c%r8", 444 | "RES", "%c,%r8", "xcb b10%c%r8", 445 | "SET", "%c,%r8", "xcb b11%c%r8", 446 | "CALL", "%i16", "xcd %i16", 447 | "OUT", "(%i8),A", "xd3 %i8", 448 | "EXX", "", "xd9", 449 | "IN", "A,(%i8)", "xdb %i8", 450 | "INC", "IXH", "xdd x24", 451 | "DEC", "IXH", "xdd x25", 452 | "INC", "IXL", "xdd x2c", 453 | "DEC", "IXL", "xdd x2d", 454 | "LD", "B,IXH", "xdd x44", 455 | "LD", "B,IXL", "xdd x45", 456 | "LD", "C,IXH", "xdd x4c", 457 | "LD", "C,IXL", "xdd x4d", 458 | "LD", "D,IXH", "xdd x54", 459 | "LD", "D,IXL", "xdd x55", 460 | "LD", "E,IXH", "xdd x5c", 461 | "LD", "E,IXL", "xdd x5d", 462 | "LD", "IXH,B", "xdd x60", 463 | "LD", "IXH,C", "xdd x61", 464 | "LD", "IXH,D", "xdd x62", 465 | "LD", "IXH,E", "xdd x63", 466 | "LD", "IXH,IXH", "xdd x64", 467 | "LD", "IXH,IXL", "xdd x65", 468 | "LD", "IXH,A", "xdd x67", 469 | "LD", "IXL,B", "xdd x68", 470 | "LD", "IXL,C", "xdd x69", 471 | "LD", "IXL,D", "xdd x6a", 472 | "LD", "IXL,E", "xdd x6b", 473 | "LD", "IXL,IXH", "xdd x6c", 474 | "LD", "IXL,IXL", "xdd x6d", 475 | "LD", "IXL,A", "xdd x6f", 476 | "LD", "A,IXH", "xdd x7c", 477 | "LD", "A,IXL", "xdd x7d", 478 | "LD", "IXH,%i8", "xdd x26 %i8", 479 | "LD", "IXL,%i8", "xdd x2e %i8", 480 | "ADD", "A,IXH", "xdd x84", 481 | "ADD", "A,IXL", "xdd x85", 482 | "ADC", "A,IXH", "xdd x8c", 483 | "ADC", "A,IXL", "xdd x8d", 484 | "SUB", "IXH", "xdd x94", 485 | "SUB", "IXL", "xdd x95", 486 | "SBC", "A,IXH", "xdd x9c", 487 | "SBC", "A,IXL", "xdd x9d", 488 | "AND", "IXH", "xdd xa4", 489 | "AND", "IXL", "xdd xa5", 490 | "XOR", "IXH", "xdd xac", 491 | "XOR", "IXL", "xdd xad", 492 | "OR", "IXH", "xdd xb4", 493 | "OR", "IXL", "xdd xb5", 494 | "CP", "IXH", "xdd xbc", 495 | "CP", "IXL", "xdd xbd", 496 | "ADD", "IX,BC", "xdd x09", 497 | "ADD", "IX,DE", "xdd x19", 498 | "LD", "IX,(%i16)", "xdd x2a %i16", 499 | "LD", "IX,%i16", "xdd x21 %i16", 500 | "LD", "(%i16),IX", "xdd x22 %i16", 501 | "INC", "IX", "xdd x23", 502 | "ADD", "IX,IX", "xdd x29", 503 | "DEC", "IX", "xdd x2b", 504 | "INC", "(IX%d8)", "xdd x34 %d8", 505 | "DEC", "(IX%d8)", "xdd x35 %d8", 506 | "ADD", "IX,SP", "xdd x39", 507 | "ADD", "A,(IX%d8)", "xdd x86 %d8", 508 | "ADC", "A,(IX%d8)", "xdd x8e %d8", 509 | "SUB", "(IX%d8)", "xdd x96 %d8", 510 | "SBC", "A,(IX%d8)", "xdd x9e %d8", 511 | "AND", "(IX%d8)", "xdd xa6 %d8", 512 | "XOR", "(IX%d8)", "xdd xae %d8", 513 | "OR", "(IX%d8)", "xdd xb6 %d8", 514 | "CP", "(IX%d8)", "xdd xbe %d8", 515 | "RLC", "(IX%d8)", "xdd xcb %d8 x06", 516 | "RRC", "(IX%d8)", "xdd xcb %d8 x0e", 517 | "RL", "(IX%d8)", "xdd xcb %d8 x16", 518 | "RR", "(IX%d8)", "xdd xcb %d8 x1e", 519 | "SLA", "(IX%d8)", "xdd xcb %d8 x26", 520 | "SRA", "(IX%d8)", "xdd xcb %d8 x2e", 521 | "SRL", "(IX%d8)", "xdd xcb %d8 x3e", 522 | "BIT", "%c,(IX%d8)", "xdd xcb %d8 b01%c110", 523 | "RES", "%c,(IX%d8)", "xdd xcb %d8 b10%c110", 524 | "SET", "%c,(IX%d8)", "xdd xcb %d8 b11%c110", 525 | "POP", "IX", "xdd xe1", 526 | "EX", "(SP),IX", "xdd xe3", 527 | "PUSH", "IX", "xdd xe5", 528 | "JP", "(IX)", "xdd xe9", 529 | "LD", "SP,IX", "xdd xf9", 530 | "EX", "(SP),HL", "xe3", 531 | "JP", "(HL)", "xe9", 532 | "EX", "DE,HL", "xeb", 533 | "IN", "%s8,(C)", "xed b01%s8000", 534 | "OUT", "(C),%s8", "xed b01%s8001", 535 | "SBC", "HL,%r16", "xed b01%r160010", 536 | "LD", "(%i16),%r16", "xed b01%r160011 %i16", 537 | "NEG", "", "xed x44", 538 | "RETN", "", "xed x45", 539 | "IM", "0", "xed x46", 540 | "LD", "I,A", "xed x47", 541 | "ADC", "HL,%r16", "xed b01%r161010", 542 | "LD", "%r16,(%i16)", "xed b01%r161011 %i16", 543 | "RETI", "", "xed x4d", 544 | "LD", "R,A", "xed x4f", 545 | "IM", "1", "xed x56", 546 | "LD", "A,I", "xed x57", 547 | "IM", "2", "xed x5e", 548 | "LD", "A,R", "xed x5f", 549 | "RRD", "", "xed x67", 550 | "RLD", "", "xed x6f", 551 | "LDI", "", "xed xa0", 552 | "CPI", "", "xed xa1", 553 | "INI", "", "xed xa2", 554 | "OUTI", "", "xed xa3", 555 | "LDD", "", "xed xa8", 556 | "CPD", "", "xed xa9", 557 | "IND", "", "xed xaa", 558 | "OUTD", "", "xed xab", 559 | "LDIR", "", "xed xb0", 560 | "CPIR", "", "xed xb1", 561 | "INIR", "", "xed xb2", 562 | "OTIR", "", "xed xb3", 563 | "LDDR", "", "xed xb8", 564 | "CPDR", "", "xed xb9", 565 | "INDR", "", "xed xba", 566 | "OTDR", "", "xed xbb", 567 | "DI", "", "xf3", 568 | "LD", "SP,HL", "xf9", 569 | "EI", "", "xfb", 570 | "INC", "IYH", "xfd x24", 571 | "DEC", "IYH", "xfd x25", 572 | "INC", "IYL", "xfd x2c", 573 | "DEC", "IYL", "xfd x2d", 574 | "LD", "B,IYH", "xfd x44", 575 | "LD", "B,IYL", "xfd x45", 576 | "LD", "C,IYH", "xfd x4c", 577 | "LD", "C,IYL", "xfd x4d", 578 | "LD", "D,IYH", "xfd x54", 579 | "LD", "D,IYL", "xfd x55", 580 | "LD", "E,IYH", "xfd x5c", 581 | "LD", "E,IYL", "xfd x5d", 582 | "LD", "IYH,B", "xfd x60", 583 | "LD", "IYH,C", "xfd x61", 584 | "LD", "IYH,D", "xfd x62", 585 | "LD", "IYH,E", "xfd x63", 586 | "LD", "IYH,IYH", "xfd x64", 587 | "LD", "IYH,IYL", "xfd x65", 588 | "LD", "IYH,A", "xfd x67", 589 | "LD", "IYL,B", "xfd x68", 590 | "LD", "IYL,C", "xfd x69", 591 | "LD", "IYL,D", "xfd x6a", 592 | "LD", "IYL,E", "xfd x6b", 593 | "LD", "IYL,IYH", "xfd x6c", 594 | "LD", "IYL,IYL", "xfd x6d", 595 | "LD", "IYL,A", "xfd x6f", 596 | "LD", "A,IYH", "xfd x7c", 597 | "LD", "A,IYL", "xfd x7d", 598 | "LD", "IYH,%i8", "xfd x26 %i8", 599 | "LD", "IYL,%i8", "xfd x2e %i8", 600 | "ADD", "A,IYH", "xfd x84", 601 | "ADD", "A,IYL", "xfd x85", 602 | "ADC", "A,IYH", "xfd x8c", 603 | "ADC", "A,IYL", "xfd x8d", 604 | "SUB", "IYH", "xfd x94", 605 | "SUB", "IYL", "xfd x95", 606 | "SBC", "A,IYH", "xfd x9c", 607 | "SBC", "A,IYL", "xfd x9d", 608 | "AND", "IYH", "xfd xa4", 609 | "AND", "IYL", "xfd xa5", 610 | "XOR", "IYH", "xfd xac", 611 | "XOR", "IYL", "xfd xad", 612 | "OR", "IYH", "xfd xb4", 613 | "OR", "IYL", "xfd xb5", 614 | "CP", "IYH", "xfd xbc", 615 | "CP", "IYL", "xfd xbd", 616 | "ADD", "IY,BC", "xfd x09", 617 | "ADD", "IY,DE", "xfd x19", 618 | "LD", "IY,(%i16)", "xfd x2a %i16", 619 | "LD", "IY,%i16", "xfd x21 %i16", 620 | "LD", "(%i16),IY", "xfd x22 %i16", 621 | "INC", "IY", "xfd x23", 622 | "ADD", "IY,IY", "xfd x29", 623 | "DEC", "IY", "xfd x2b", 624 | "INC", "(IY%d8)", "xfd x34 %d8", 625 | "DEC", "(IY%d8)", "xfd x35 %d8", 626 | "ADD", "IY,SP", "xfd x39", 627 | "ADD", "A,(IY%d8)", "xfd x86 %d8", 628 | "ADC", "A,(IY%d8)", "xfd x8e %d8", 629 | "SUB", "(IY%d8)", "xfd x96 %d8", 630 | "SBC", "A,(IY%d8)", "xfd x9e %d8", 631 | "AND", "(IY%d8)", "xfd xa6 %d8", 632 | "XOR", "(IY%d8)", "xfd xae %d8", 633 | "OR", "(IY%d8)", "xfd xb6 %d8", 634 | "CP", "(IY%d8)", "xfd xbe %d8", 635 | "RLC", "(IY%d8)", "xfd xcb %d8 x06", 636 | "RRC", "(IY%d8)", "xfd xcb %d8 x0e", 637 | "RL", "(IY%d8)", "xfd xcb %d8 x16", 638 | "RR", "(IY%d8)", "xfd xcb %d8 x1e", 639 | "SLA", "(IY%d8)", "xfd xcb %d8 x26", 640 | "SRA", "(IY%d8)", "xfd xcb %d8 x2e", 641 | "SRL", "(IY%d8)", "xfd xcb %d8 x3e", 642 | "BIT", "%c,(IY%d8)", "xfd xcb %d8 b01%c110", 643 | "RES", "%c,(IY%d8)", "xfd xcb %d8 b10%c110", 644 | "SET", "%c,(IY%d8)", "xfd xcb %d8 b11%c110", 645 | "POP", "IY", "xfd xe1", 646 | "EX", "(SP),IY", "xfd xe3", 647 | "PUSH", "IY", "xfd xe5", 648 | "JP", "(IY)", "xfd xe9", 649 | "LD", "SP,IY", "xfd xf9", 650 | "LD", "%r8,%i8", "b00%r8110 %i8", 651 | "LD", "%r8,%t8", "b01%r8%t8", 652 | "LD", "%t8,%r8", "b01%t8%r8", 653 | "ADD", "A,%r8", "b10000%r8", 654 | "ADC", "A,%r8", "b10001%r8", 655 | "SUB", "%r8", "b10010%r8", 656 | "SBC", "A,%r8", "b10011%r8", 657 | "AND", "%r8", "b10100%r8", 658 | "XOR", "%r8", "b10101%r8", 659 | "OR", "%r8", "b10110%r8", 660 | "CP", "%r8", "b10111%r8", 661 | "ADD", "A,%i8", "xc6 %i8", 662 | "ADC", "A,%i8", "xce %i8", 663 | "SUB", "%i8", "xd6 %i8", 664 | "SBC", "A,%i8", "xde %i8", 665 | "AND", "%i8", "xe6 %i8", 666 | "XOR", "%i8", "xee %i8", 667 | "OR", "%i8", "xf6 %i8", 668 | "CP", "%i8", "xfe %i8", 669 | "JP", "%i16", "xc3 %i16", 670 | "LD", "%r16,%i16", "b00%r160001 %i16", 671 | NULL, NULL, NULL, 672 | }; 673 | 674 | char *regs[] = { 675 | "B", 676 | "C", 677 | "D", 678 | "E", 679 | "H", 680 | "L", 681 | "(HL)", 682 | "A", 683 | 684 | "BC", 685 | "DE", 686 | "HL", 687 | "SP", 688 | 689 | "BC", 690 | "DE", 691 | "HL", 692 | "AF", 693 | 694 | "NZ", 695 | "Z", 696 | "NC", 697 | "C", 698 | "PO", 699 | "PE", 700 | "P", 701 | "M", 702 | }; 703 | 704 | void message(int error, char *message); 705 | char *match_register(char *, int, int *); 706 | char *match_expression(char *, int *); 707 | char *match_expression_level1(char *, int *); 708 | char *match_expression_level2(char *, int *); 709 | char *match_expression_level3(char *, int *); 710 | char *match_expression_level4(char *, int *); 711 | char *match_expression_level5(char *, int *); 712 | char *match_expression_level6(char *, int *); 713 | 714 | /* 715 | ** Define a new label 716 | */ 717 | struct label *define_label(char *name, int value) 718 | { 719 | struct label *label; 720 | struct label *explore; 721 | int c; 722 | 723 | /* Allocate label */ 724 | label = malloc(sizeof(struct label) + strlen(name)); 725 | if (label == NULL) { 726 | fprintf(stderr, "Out of memory for label\n"); 727 | exit(1); 728 | return NULL; 729 | } 730 | 731 | /* Fill label */ 732 | label->left = NULL; 733 | label->right = NULL; 734 | label->value = value; 735 | strcpy(label->name, name); 736 | 737 | /* Populate binary tree */ 738 | if (label_list == NULL) { 739 | label_list = label; 740 | } else { 741 | explore = label_list; 742 | while (1) { 743 | c = strcmp(label->name, explore->name); 744 | if (c < 0) { 745 | if (explore->left == NULL) { 746 | explore->left = label; 747 | break; 748 | } 749 | explore = explore->left; 750 | } else if (c > 0) { 751 | if (explore->right == NULL) { 752 | explore->right = label; 753 | break; 754 | } 755 | explore = explore->right; 756 | } 757 | } 758 | } 759 | return label; 760 | } 761 | 762 | /* 763 | ** Find a label 764 | */ 765 | struct label *find_label(char *name) 766 | { 767 | struct label *explore; 768 | int c; 769 | 770 | /* Follows a binary tree */ 771 | explore = label_list; 772 | while (explore != NULL) { 773 | c = strcmp(name, explore->name); 774 | if (c == 0) 775 | return explore; 776 | if (c < 0) 777 | explore = explore->left; 778 | else 779 | explore = explore->right; 780 | } 781 | return NULL; 782 | } 783 | 784 | /* 785 | ** Sort recursively labels (already done by binary tree) 786 | */ 787 | void sort_labels(struct label *node) 788 | { 789 | if (node->left != NULL) 790 | sort_labels(node->left); 791 | if (listing != NULL) 792 | fprintf(listing, "%-20s %04x\n", node->name, node->value); 793 | if (symbol != NULL) 794 | fprintf(symbol, "%s: equ %08xh\n", node->name, node->value); 795 | if (node->right != NULL) 796 | sort_labels(node->right); 797 | } 798 | 799 | /* 800 | ** Avoid spaces in input 801 | */ 802 | char *avoid_spaces(char *p) 803 | { 804 | while (isspace(*p)) 805 | p++; 806 | return p; 807 | } 808 | 809 | /* 810 | ** Check for a label character 811 | */ 812 | int islabel(int c) 813 | { 814 | return isalpha(c) || isdigit(c) || c == '_' || c == '.' || c == '#'; 815 | } 816 | 817 | /* 818 | ** Match register 819 | */ 820 | char *match_register(char *p, int type, int *value) 821 | { 822 | char reg[5]; 823 | int c; 824 | int base; 825 | int length; 826 | 827 | p = avoid_spaces(p); 828 | if (type == 0) { /* 8-bit */ 829 | if (p[0] == '(' && p[1] == 'H' && p[2] == 'L' && p[3] == ')') { 830 | memcpy(reg, p, 4); 831 | reg[4] = '\0'; 832 | p += 4; 833 | } else if (!isalpha(p[0]) || islabel(p[1])) { 834 | return NULL; 835 | } else { 836 | reg[0] = *p++; 837 | reg[1] = '\0'; 838 | } 839 | base = 0; 840 | length = 8; 841 | } else if (type < 3) { /* 16-bit */ 842 | if (!isalpha(p[0]) || !isalpha(p[1]) || islabel(p[2])) 843 | return NULL; 844 | reg[0] = *p++; 845 | reg[1] = *p++; 846 | reg[2] = '\0'; 847 | if (type == 1) 848 | base = 8; 849 | else 850 | base = 12; 851 | length = 4; 852 | } else { /* Flags */ 853 | if (!isalpha(p[0])) 854 | return NULL; 855 | reg[0] = *p++; 856 | if (islabel(*p)) { 857 | reg[1] = *p++; 858 | if (islabel(*p)) 859 | return NULL; 860 | reg[2] = '\0'; 861 | } else { 862 | reg[1] = '\0'; 863 | } 864 | base = 16; 865 | length = 8; 866 | } 867 | for (c = base; c < base + length; c++) 868 | if (strcmp(reg, regs[c]) == 0) 869 | break; 870 | if (c < base + length) { 871 | *value = c - base; 872 | return p; 873 | } 874 | return NULL; 875 | } 876 | 877 | /* 878 | ** Read character for string or character literal 879 | */ 880 | char *read_character(char *p, int *c) 881 | { 882 | if (*p == '\\') { 883 | p++; 884 | if (*p == '\'') { 885 | *c = '\''; 886 | p++; 887 | } else if (*p == '\"') { 888 | *c = '"'; 889 | p++; 890 | } else if (*p == '\\') { 891 | *c = '\\'; 892 | p++; 893 | } else if (*p == 'a') { 894 | *c = 0x07; 895 | p++; 896 | } else if (*p == 'b') { 897 | *c = 0x08; 898 | p++; 899 | } else if (*p == 't') { 900 | *c = 0x09; 901 | p++; 902 | } else if (*p == 'n') { 903 | *c = 0x0a; 904 | p++; 905 | } else if (*p == 'v') { 906 | *c = 0x0b; 907 | p++; 908 | } else if (*p == 'f') { 909 | *c = 0x0c; 910 | p++; 911 | } else if (*p == 'r') { 912 | *c = 0x0d; 913 | p++; 914 | } else if (*p == 'e') { 915 | *c = 0x1b; 916 | p++; 917 | } else if (*p >= '0' && *p <= '7') { 918 | *c = 0; 919 | while (*p >= '0' && *p <= '7') { 920 | *c = *c * 8 + (*p - '0'); 921 | p++; 922 | } 923 | } else { 924 | p--; 925 | *c = *p; 926 | p++; 927 | message(1, "bad escape inside string"); 928 | } 929 | } else { 930 | *c = *p; 931 | p++; 932 | } 933 | return p; 934 | } 935 | 936 | /* 937 | ** Match expression (top tier) 938 | */ 939 | char *match_expression(char *p, int *value) 940 | { 941 | int value1; 942 | 943 | p = match_expression_level1(p, value); 944 | if (p == NULL) 945 | return NULL; 946 | while (1) { 947 | p = avoid_spaces(p); 948 | if (*p == '|') { /* Binary OR */ 949 | p++; 950 | value1 = *value; 951 | p = match_expression_level1(p, value); 952 | if (p == NULL) 953 | return NULL; 954 | *value |= value1; 955 | } else { 956 | return p; 957 | } 958 | } 959 | } 960 | 961 | /* 962 | ** Match expression 963 | */ 964 | char *match_expression_level1(char *p, int *value) 965 | { 966 | int value1; 967 | 968 | p = match_expression_level2(p, value); 969 | if (p == NULL) 970 | return NULL; 971 | while (1) { 972 | p = avoid_spaces(p); 973 | if (*p == '^') { /* Binary XOR */ 974 | p++; 975 | value1 = *value; 976 | p = match_expression_level2(p, value); 977 | if (p == NULL) 978 | return NULL; 979 | *value ^= value1; 980 | } else { 981 | return p; 982 | } 983 | } 984 | } 985 | 986 | /* 987 | ** Match expression 988 | */ 989 | char *match_expression_level2(char *p, int *value) 990 | { 991 | int value1; 992 | 993 | p = match_expression_level3(p, value); 994 | if (p == NULL) 995 | return NULL; 996 | while (1) { 997 | p = avoid_spaces(p); 998 | if (*p == '&') { /* Binary AND */ 999 | p++; 1000 | value1 = *value; 1001 | p = match_expression_level3(p, value); 1002 | if (p == NULL) 1003 | return NULL; 1004 | *value &= value1; 1005 | } else { 1006 | return p; 1007 | } 1008 | } 1009 | } 1010 | 1011 | /* 1012 | ** Match expression 1013 | */ 1014 | char *match_expression_level3(char *p, int *value) 1015 | { 1016 | int value1; 1017 | 1018 | p = match_expression_level4(p, value); 1019 | if (p == NULL) 1020 | return NULL; 1021 | while (1) { 1022 | p = avoid_spaces(p); 1023 | if (*p == '<' && p[1] == '<') { /* Shift to left */ 1024 | p += 2; 1025 | value1 = *value; 1026 | p = match_expression_level4(p, value); 1027 | if (p == NULL) 1028 | return NULL; 1029 | *value = value1 << *value; 1030 | } else if (*p == '>' && p[1] == '>') { /* Shift to right */ 1031 | p += 2; 1032 | value1 = *value; 1033 | p = match_expression_level4(p, value); 1034 | if (p == NULL) 1035 | return NULL; 1036 | *value = value1 >> *value; 1037 | } else { 1038 | return p; 1039 | } 1040 | } 1041 | } 1042 | 1043 | /* 1044 | ** Match expression 1045 | */ 1046 | char *match_expression_level4(char *p, int *value) 1047 | { 1048 | int value1; 1049 | 1050 | p = match_expression_level5(p, value); 1051 | if (p == NULL) 1052 | return NULL; 1053 | while (1) { 1054 | p = avoid_spaces(p); 1055 | if (*p == '+') { /* Add operator */ 1056 | p++; 1057 | value1 = *value; 1058 | p = match_expression_level5(p, value); 1059 | if (p == NULL) 1060 | return NULL; 1061 | *value = value1 + *value; 1062 | } else if (*p == '-') { /* Subtract operator */ 1063 | p++; 1064 | value1 = *value; 1065 | p = match_expression_level5(p, value); 1066 | if (p == NULL) 1067 | return NULL; 1068 | *value = value1 - *value; 1069 | } else { 1070 | return p; 1071 | } 1072 | } 1073 | } 1074 | 1075 | /* 1076 | ** Match expression 1077 | */ 1078 | char *match_expression_level5(char *p, int *value) 1079 | { 1080 | int value1; 1081 | 1082 | p = match_expression_level6(p, value); 1083 | if (p == NULL) 1084 | return NULL; 1085 | while (1) { 1086 | p = avoid_spaces(p); 1087 | if (*p == '*') { /* Multiply operator */ 1088 | p++; 1089 | value1 = *value; 1090 | p = match_expression_level6(p, value); 1091 | if (p == NULL) 1092 | return NULL; 1093 | *value = value1 * *value; 1094 | } else if (*p == '/') { /* Division operator */ 1095 | p++; 1096 | value1 = *value; 1097 | p = match_expression_level6(p, value); 1098 | if (p == NULL) 1099 | return NULL; 1100 | if (*value == 0) { 1101 | if (assembler_step == 2) 1102 | message(1, "division by zero"); 1103 | *value = 1; 1104 | } 1105 | *value = (unsigned) value1 / *value; 1106 | } else if (*p == '%') { /* Modulo operator */ 1107 | p++; 1108 | value1 = *value; 1109 | p = match_expression_level6(p, value); 1110 | if (p == NULL) 1111 | return NULL; 1112 | if (*value == 0) { 1113 | if (assembler_step == 2) 1114 | message(1, "modulo by zero"); 1115 | *value = 1; 1116 | } 1117 | *value = value1 % *value; 1118 | } else { 1119 | return p; 1120 | } 1121 | } 1122 | } 1123 | 1124 | /* 1125 | ** Match expression (bottom tier) 1126 | */ 1127 | char *match_expression_level6(char *p, int *value) 1128 | { 1129 | int number; 1130 | int c; 1131 | char *p2; 1132 | struct label *label; 1133 | 1134 | p = avoid_spaces(p); 1135 | if (*p == '(') { /* Handle parenthesized expressions */ 1136 | p++; 1137 | p = match_expression(p, value); 1138 | if (p == NULL) 1139 | return NULL; 1140 | p = avoid_spaces(p); 1141 | if (*p != ')') 1142 | return NULL; 1143 | p++; 1144 | return p; 1145 | } 1146 | if (*p == '-') { /* Simple negation */ 1147 | p++; 1148 | p = match_expression_level6(p, value); 1149 | if (p == NULL) 1150 | return NULL; 1151 | *value = -*value; 1152 | return p; 1153 | } 1154 | if (*p == '+') { /* Unary */ 1155 | p++; 1156 | p = match_expression_level6(p, value); 1157 | if (p == NULL) 1158 | return NULL; 1159 | return p; 1160 | } 1161 | if (p[0] == '0' && tolower(p[1]) == 'b') { /* Binary */ 1162 | p += 2; 1163 | number = 0; 1164 | while (p[0] == '0' || p[0] == '1' || p[0] == '_') { 1165 | if (p[0] != '_') { 1166 | number <<= 1; 1167 | if (p[0] == '1') 1168 | number |= 1; 1169 | } 1170 | p++; 1171 | } 1172 | *value = number; 1173 | return p; 1174 | } 1175 | if (p[0] == '0' && tolower(p[1]) == 'x' && isxdigit(p[2])) { /* Hexadecimal */ 1176 | p += 2; 1177 | number = 0; 1178 | while (isxdigit(p[0])) { 1179 | c = toupper(p[0]); 1180 | c = c - '0'; 1181 | if (c > 9) 1182 | c -= 7; 1183 | number = (number << 4) | c; 1184 | p++; 1185 | } 1186 | *value = number; 1187 | return p; 1188 | } 1189 | if (p[0] == '$' && isxdigit(p[1])) { /* Hexadecimal */ 1190 | p++; 1191 | number = 0; 1192 | while (isxdigit(p[0])) { 1193 | c = toupper(p[0]); 1194 | c = c - '0'; 1195 | if (c > 9) 1196 | c -= 7; 1197 | number = (number << 4) | c; 1198 | p++; 1199 | } 1200 | *value = number; 1201 | return p; 1202 | } 1203 | if (p[0] == '\'') { /* Character constant */ 1204 | p++; 1205 | p = read_character(p, value); 1206 | if (p[0] != '\'') { 1207 | message(1, "Missing apostrophe"); 1208 | } else { 1209 | p++; 1210 | } 1211 | return p; 1212 | } 1213 | if (isdigit(*p)) { /* Decimal */ 1214 | number = 0; 1215 | while (isdigit(p[0])) { 1216 | c = p[0] - '0'; 1217 | number = number * 10 + c; 1218 | p++; 1219 | } 1220 | *value = number; 1221 | return p; 1222 | } 1223 | if (*p == '$' && p[1] == '$') { /* Start address */ 1224 | p += 2; 1225 | *value = start_address; 1226 | return p; 1227 | } 1228 | if (*p == '$') { /* Current address */ 1229 | p++; 1230 | *value = address; 1231 | return p; 1232 | } 1233 | if (isalpha(*p) || *p == '_' || *p == '.' || *p == '#') { /* Label */ 1234 | if (*p == '.') { 1235 | strcpy(expr_name, global_label); 1236 | p2 = expr_name; 1237 | while (*p2) 1238 | p2++; 1239 | } else { 1240 | p2 = expr_name; 1241 | } 1242 | while (islabel(*p)) 1243 | *p2++ = *p++; 1244 | *p2 = '\0'; 1245 | for (c = 0; c < 24; c++) 1246 | if (strcmp(expr_name, regs[c]) == 0) 1247 | return NULL; 1248 | label = find_label(expr_name); 1249 | if (label == NULL) { 1250 | *value = 0; 1251 | undefined++; 1252 | strcpy(undefined_name, expr_name); 1253 | } else { 1254 | *value = label->value; 1255 | } 1256 | return p; 1257 | } 1258 | return NULL; 1259 | } 1260 | 1261 | /* 1262 | ** Emit one byte to output 1263 | */ 1264 | void emit_byte(int byte) 1265 | { 1266 | char buf[1]; 1267 | 1268 | if (assembler_step == 2) { 1269 | if (output_address == -1) { 1270 | output_address = address; 1271 | } else if (address < output_address) { 1272 | fprintf(stderr, "Error: ORG went backward %04x vs previous %04x\n", address, output_address); 1273 | } else if (address > output_address) { 1274 | do { 1275 | buf[0] = 0xff; 1276 | fwrite(buf, 1, 1, output); 1277 | bytes++; 1278 | output_address++; 1279 | } while (output_address < address) ; 1280 | } 1281 | if (g != NULL && g < generated + sizeof(generated)) 1282 | *g++ = byte; 1283 | buf[0] = byte; 1284 | /* Cannot use fputc because DeSmet C expands to CR LF */ 1285 | fwrite(buf, 1, 1, output); 1286 | bytes++; 1287 | output_address++; 1288 | } 1289 | address++; 1290 | } 1291 | 1292 | /* 1293 | ** Search for a match with instruction 1294 | */ 1295 | char *match(char *p, char *pattern, char *decode) 1296 | { 1297 | char *start; 1298 | char *p2; 1299 | int c; 1300 | int d; 1301 | int bit; 1302 | char *base; 1303 | unsigned char bytes[8]; 1304 | int which; 1305 | 1306 | start = p; 1307 | undefined = 0; 1308 | while (*pattern) { 1309 | /* fputc(*pattern, stdout);*/ 1310 | if (*pattern == '%') { /* Special */ 1311 | pattern++; 1312 | if (*pattern == 'd') { /* Indexed addressing */ 1313 | pattern++; 1314 | if (*pattern == '8') { 1315 | pattern++; 1316 | p2 = match_expression(p, &instruction_offset); 1317 | if (p2 == NULL) 1318 | return NULL; 1319 | p = p2; 1320 | } else { 1321 | return NULL; 1322 | } 1323 | } else if (*pattern == 'f') { /* Flag */ 1324 | pattern++; 1325 | p2 = match_register(p, 3, &instruction_register); 1326 | if (p2 == NULL) 1327 | return NULL; 1328 | p = p2; 1329 | } else if (*pattern == 'r') { /* Register */ 1330 | pattern++; 1331 | if (*pattern == '8') { 1332 | pattern++; 1333 | p2 = match_register(p, 0, &instruction_register); 1334 | if (p2 == NULL) 1335 | return NULL; 1336 | p = p2; 1337 | } else if (*pattern == '1' && pattern[1] == '6') { 1338 | pattern += 2; 1339 | p2 = match_register(p, 1, &instruction_register); 1340 | if (p2 == NULL) 1341 | return NULL; 1342 | p = p2; 1343 | } else { 1344 | return NULL; 1345 | } 1346 | } else if (*pattern == 's') { /* Register */ 1347 | pattern++; 1348 | if (*pattern == '8') { 1349 | pattern++; 1350 | p2 = match_register(p, 0, &instruction_register_2); 1351 | if (p2 == NULL) 1352 | return NULL; 1353 | p = p2; 1354 | } else if (*pattern == '1' && pattern[1] == '6') { 1355 | pattern += 2; 1356 | p2 = match_register(p, 2, &instruction_register_2); 1357 | if (p2 == NULL) 1358 | return NULL; 1359 | p = p2; 1360 | } else { 1361 | return NULL; 1362 | } 1363 | } else if (*pattern == 't') { /* Register */ 1364 | pattern++; 1365 | if (*pattern == '8') { 1366 | pattern++; 1367 | p2 = match_register(p, 0, &instruction_register_2); 1368 | if (p2 == NULL) 1369 | return NULL; 1370 | if (instruction_register_2 == 6) /* HL */ 1371 | return NULL; 1372 | p = p2; 1373 | } else { 1374 | return NULL; 1375 | } 1376 | } else if (*pattern == 'i') { /* Immediate */ 1377 | pattern++; 1378 | if (*pattern == '8') { 1379 | pattern++; 1380 | p2 = match_expression(p, &instruction_value); 1381 | if (p2 == NULL) 1382 | return NULL; 1383 | if (processor == CPU_6502) { 1384 | if ((start == p || p[-1] != '#') && (instruction_value & 0xff00) != 0) 1385 | return NULL; 1386 | } 1387 | p = p2; 1388 | } else if (*pattern == '1' && pattern[1] == '6') { 1389 | pattern += 2; 1390 | p2 = match_expression(p, &instruction_value); 1391 | if (p2 == NULL) 1392 | return NULL; 1393 | p = p2; 1394 | } else { 1395 | return NULL; 1396 | } 1397 | } else if (*pattern == 'b') { /* Short address */ 1398 | pattern++; 1399 | if (*pattern == '8') { 1400 | pattern++; 1401 | p2 = match_expression(p, &instruction_value); 1402 | if (p2 == NULL) 1403 | return NULL; 1404 | p = p2; 1405 | } else { 1406 | return NULL; 1407 | } 1408 | } else if (*pattern == 'a') { /* Address for jump */ 1409 | pattern++; 1410 | if (*pattern == '8') { 1411 | pattern++; 1412 | p = avoid_spaces(p); 1413 | p2 = match_expression(p, &instruction_value); 1414 | if (p2 == NULL) 1415 | return NULL; 1416 | p = p2; 1417 | } else { 1418 | return NULL; 1419 | } 1420 | } else if (*pattern == 'c') { /* Bit */ 1421 | pattern++; 1422 | p2 = match_expression(p, &instruction_value); 1423 | if (p2 == NULL) 1424 | return NULL; 1425 | if (undefined == 0 && (instruction_value < 0 || instruction_value > 7)) 1426 | return NULL; 1427 | p = p2; 1428 | } else { 1429 | return NULL; 1430 | } 1431 | continue; 1432 | } 1433 | if (toupper(*p) != *pattern) 1434 | return NULL; 1435 | p++; 1436 | if (*pattern == ',') /* Allow spaces after comma */ 1437 | p = avoid_spaces(p); 1438 | pattern++; 1439 | } 1440 | /* 1441 | ** Not a match if there is something extra in the line. 1442 | ** It happens in the case LD A,R that can be confused with LD A,read_value. 1443 | */ 1444 | if (*p != '\0' && *p != ';' && !isspace(*p)) 1445 | return NULL; 1446 | 1447 | /* 1448 | ** Instruction properly matched, now generate binary 1449 | */ 1450 | which = 0; 1451 | base = decode; 1452 | while (*decode) { 1453 | decode = avoid_spaces(decode); 1454 | if (decode[0] == 'x') { /* Byte */ 1455 | c = toupper(decode[1]); 1456 | c -= '0'; 1457 | if (c > 9) 1458 | c -= 7; 1459 | d = toupper(decode[2]); 1460 | d -= '0'; 1461 | if (d > 9) 1462 | d -= 7; 1463 | c = (c << 4) | d; 1464 | bytes[which++] = c; 1465 | decode += 3; 1466 | } else { /* Binary */ 1467 | if (*decode == 'b') 1468 | decode++; 1469 | bit = 0; 1470 | c = 0; 1471 | d = 0; 1472 | while (bit < 8) { 1473 | if (decode[0] == '0') { /* Zero */ 1474 | decode++; 1475 | bit++; 1476 | } else if (decode[0] == '1') { /* One */ 1477 | c |= 0x80 >> bit; 1478 | decode++; 1479 | bit++; 1480 | } else if (decode[0] == '%') { /* Special */ 1481 | decode++; 1482 | if (decode[0] == 'r') { /* Register field */ 1483 | decode++; 1484 | if (decode[0] == '8') { 1485 | decode++; 1486 | c |= instruction_register << (5 - bit); 1487 | bit += 3; 1488 | } else if (decode[0] == '1' && decode[1] == '6') { 1489 | decode += 2; 1490 | c |= instruction_register << (6 - bit); 1491 | bit += 2; 1492 | } 1493 | } else if (decode[0] == 'f') { /* Flag */ 1494 | decode++; 1495 | c |= instruction_register << (5 - bit); 1496 | bit += 3; 1497 | } else if (decode[0] == 's' || decode[0] == 't') { /* Register field */ 1498 | decode++; 1499 | if (decode[0] == '8') { 1500 | decode++; 1501 | c |= instruction_register_2 << (5 - bit); 1502 | bit += 3; 1503 | } else if (decode[0] == '1' && decode[1] == '6') { 1504 | decode += 2; 1505 | c |= instruction_register_2 << (6 - bit); 1506 | bit += 2; 1507 | } 1508 | } else if (decode[0] == 'd') { /* Index offset */ 1509 | decode += 2; 1510 | c = instruction_offset; 1511 | if (assembler_step == 2 && (c < -128 || c > 127)) 1512 | message(1, "offset too long"); 1513 | break; 1514 | } else if (decode[0] == 'i') { 1515 | if (decode[1] == '8') { 1516 | decode += 2; 1517 | c = instruction_value; 1518 | break; 1519 | } 1520 | decode += 3; 1521 | c = instruction_value; 1522 | d = 1; 1523 | break; 1524 | } else if (decode[0] == 'b') { 1525 | decode += 2; 1526 | if (assembler_step == 2 && ((instruction_value & 7) != 0 || (instruction_value & ~0x3f) != 0)) 1527 | message(1, "wrong RST address"); 1528 | c |= (instruction_value >> 3) << (5 - bit); 1529 | bit += 3; 1530 | } else if (decode[0] == 'a') { 1531 | if (decode[1] == '8') { 1532 | decode += 2; 1533 | c = instruction_value - (address + 2); 1534 | if (assembler_step == 2 && (c < -128 || c > 127)) 1535 | message(1, "relative jump too long"); 1536 | } else { 1537 | struct extend_jump *new_jump; 1538 | 1539 | decode += 3; 1540 | 1541 | if (building_jumps) { 1542 | new_jump = malloc(sizeof(struct extend_jump)); 1543 | new_jump->next = NULL; 1544 | new_jump->address = address - 1; 1545 | new_jump->target = instruction_value; 1546 | new_jump->relative = 1; 1547 | if (first_jump == NULL) 1548 | first_jump = new_jump; 1549 | if (last_jump != NULL) 1550 | last_jump->next = new_jump; 1551 | last_jump = new_jump; 1552 | } else { 1553 | new_jump = current_jump; 1554 | if (new_jump == NULL) { 1555 | fprintf(stderr, "decode: internal error 3. New jump instructions!\n"); 1556 | exit(1); 1557 | } 1558 | new_jump->address = address - 1; 1559 | new_jump->target = instruction_value; 1560 | current_jump = current_jump->next; 1561 | } 1562 | if (new_jump->relative) { 1563 | c = instruction_value - (address + 2); 1564 | } else { 1565 | bytes[0] ^= 0x20; 1566 | bytes[which++] = 0x03; 1567 | bytes[which++] = 0x4c; 1568 | c = instruction_value; 1569 | d = 1; 1570 | } 1571 | } 1572 | break; 1573 | } else if (decode[0] == 'c') { 1574 | decode++; 1575 | if (assembler_step == 2 && (instruction_value & ~0x07) != 0) 1576 | message(1, "wrong bit selection"); 1577 | c |= instruction_value << (5 - bit); 1578 | bit += 3; 1579 | } else { 1580 | fprintf(stderr, "decode: internal error 2\n"); 1581 | } 1582 | } else { 1583 | fprintf(stderr, "decode: internal error 1 (%s)\n", base); 1584 | break; 1585 | } 1586 | } 1587 | bytes[which++] = c; 1588 | if (d == 1) { 1589 | d = 0; 1590 | bytes[which++] = c >> 8; 1591 | } 1592 | } 1593 | } 1594 | for (c = 0; c < which; c++) { 1595 | emit_byte(bytes[c]); 1596 | } 1597 | if (assembler_step == 2) { 1598 | if (undefined) { 1599 | fprintf(stderr, "Error: undefined label '%s' at line %d\n", undefined_name, line_number); 1600 | } 1601 | } 1602 | return p; 1603 | } 1604 | 1605 | /* 1606 | ** Convert a string to lowercase 1607 | */ 1608 | void to_lowercase(char *p) 1609 | { 1610 | while (*p) { 1611 | *p = tolower(*p); 1612 | p++; 1613 | } 1614 | } 1615 | 1616 | /* 1617 | ** Separate a portion of entry up to the first space 1618 | */ 1619 | void separate(void) 1620 | { 1621 | char *p2; 1622 | 1623 | while (*p && isspace(*p)) 1624 | p++; 1625 | prev_p = p; 1626 | p2 = part; 1627 | while (*p && !isspace(*p) && *p != ';') 1628 | *p2++ = *p++; 1629 | *p2 = '\0'; 1630 | while (*p && isspace(*p)) 1631 | p++; 1632 | } 1633 | 1634 | /* 1635 | ** Check for end of line 1636 | */ 1637 | void check_end(char *p) 1638 | { 1639 | p = avoid_spaces(p); 1640 | if (*p && *p != ';') { 1641 | fprintf(stderr, "Error: extra characters at end of line %d\n", line_number); 1642 | errors++; 1643 | } 1644 | } 1645 | 1646 | /* 1647 | ** Generate a message 1648 | */ 1649 | void message(int error, char *message) 1650 | { 1651 | if (error) { 1652 | fprintf(stderr, "Error: %s at line %d\n", message, line_number); 1653 | errors++; 1654 | } else { 1655 | fprintf(stderr, "Warning: %s at line %d\n", message, line_number); 1656 | warnings++; 1657 | } 1658 | if (listing != NULL) { 1659 | if (error) { 1660 | fprintf(listing, "Error: %s at line %d\n", message, line_number); 1661 | } else { 1662 | fprintf(listing, "Warning: %s at line %d\n", message, line_number); 1663 | } 1664 | } 1665 | } 1666 | 1667 | /* 1668 | ** Process an instruction 1669 | */ 1670 | void process_instruction(void) 1671 | { 1672 | char *p2 = NULL; 1673 | char *p3; 1674 | int c; 1675 | 1676 | if (strcmp(part, "RB") == 0) { /* Define byte */ 1677 | p = avoid_spaces(p); 1678 | undefined = 0; 1679 | p2 = match_expression(p, &instruction_value); 1680 | if (p2 == NULL) { 1681 | fprintf(stderr, "Error: bad expression at line %d\n", line_number); 1682 | return; 1683 | } 1684 | if (undefined) { 1685 | fprintf(stderr, "Error: undefined size in rb at line %d\n", line_number); 1686 | return; 1687 | } 1688 | address += instruction_value; 1689 | p = p2; 1690 | check_end(p); 1691 | return; 1692 | } 1693 | if (strcmp(part, "DB") == 0) { /* Define byte */ 1694 | while (1) { 1695 | p = avoid_spaces(p); 1696 | if (*p == '"') { /* ASCII text */ 1697 | p++; 1698 | while (*p && *p != '"') { 1699 | p = read_character(p, &c); 1700 | emit_byte(c); 1701 | } 1702 | if (*p) { 1703 | p++; 1704 | } else { 1705 | fprintf(stderr, "Error: unterminated string at line %d\n", line_number); 1706 | } 1707 | } else { 1708 | undefined = 0; 1709 | p2 = match_expression(p, &instruction_value); 1710 | if (p2 == NULL) { 1711 | fprintf(stderr, "Error: bad expression at line %d\n", line_number); 1712 | break; 1713 | } else if (assembler_step == 2 && undefined) { 1714 | fprintf(stderr, "Error: undefined label '%s' at line %d\n", undefined_name, line_number); 1715 | break; 1716 | } 1717 | emit_byte(instruction_value); 1718 | p = p2; 1719 | } 1720 | p = avoid_spaces(p); 1721 | if (*p == ',') { 1722 | p++; 1723 | continue; 1724 | } 1725 | check_end(p); 1726 | break; 1727 | } 1728 | return; 1729 | } 1730 | if (strcmp(part, "DW") == 0) { /* Define word */ 1731 | while (1) { 1732 | undefined = 0; 1733 | p2 = match_expression(p, &instruction_value); 1734 | if (p2 == NULL) { 1735 | fprintf(stderr, "Error: bad expression at line %d\n", line_number); 1736 | break; 1737 | } else if (assembler_step == 2 && undefined) { 1738 | fprintf(stderr, "Error: undefined label '%s' at line %d\n", undefined_name, line_number); 1739 | break; 1740 | } 1741 | emit_byte(instruction_value); 1742 | emit_byte(instruction_value >> 8); 1743 | p = avoid_spaces(p2); 1744 | if (*p == ',') { 1745 | p++; 1746 | continue; 1747 | } 1748 | check_end(p); 1749 | break; 1750 | } 1751 | return; 1752 | } 1753 | if (processor == CPU_Z80) { 1754 | while (part[0]) { /* Match against instruction set */ 1755 | c = 0; 1756 | while (cpu_z80_instruction_set[c] != NULL) { 1757 | if (strcmp(part, cpu_z80_instruction_set[c]) == 0) { 1758 | p2 = match(p, cpu_z80_instruction_set[c + 1], cpu_z80_instruction_set[c + 2]); 1759 | if (p2 != NULL) { 1760 | p = p2; 1761 | break; 1762 | } 1763 | } 1764 | c += 3; 1765 | } 1766 | if (cpu_z80_instruction_set[c] == NULL) { 1767 | char m[25 + MAX_SIZE]; 1768 | 1769 | sprintf(m, "Undefined instruction '%s %s'", part, p); 1770 | message(1, m); 1771 | break; 1772 | } else { 1773 | p = p2; 1774 | separate(); 1775 | } 1776 | } 1777 | } else { 1778 | while (part[0]) { /* Match against instruction set */ 1779 | c = 0; 1780 | while (cpu_6502_instruction_set[c] != NULL) { 1781 | if (strcmp(part, cpu_6502_instruction_set[c]) == 0) { 1782 | p2 = match(p, cpu_6502_instruction_set[c + 1], cpu_6502_instruction_set[c + 2]); 1783 | if (p2 != NULL) { 1784 | p = p2; 1785 | break; 1786 | } 1787 | } 1788 | c += 3; 1789 | } 1790 | if (cpu_6502_instruction_set[c] == NULL) { 1791 | char m[25 + MAX_SIZE]; 1792 | 1793 | sprintf(m, "Undefined instruction '%s %s'", part, p); 1794 | message(1, m); 1795 | break; 1796 | } else { 1797 | p = p2; 1798 | separate(); 1799 | } 1800 | } 1801 | } 1802 | } 1803 | 1804 | /* 1805 | ** Reset current address. 1806 | ** Called anytime the assembler needs to generate code. 1807 | */ 1808 | void reset_address(void) 1809 | { 1810 | output_address = address = start_address = default_start_address; 1811 | } 1812 | 1813 | /* 1814 | ** Include a binary file 1815 | */ 1816 | void incbin(char *fname, long int offset, size_t length) 1817 | { 1818 | FILE *input; 1819 | char buf[256]; 1820 | int size; 1821 | int i; 1822 | 1823 | input = fopen(fname, "rb"); 1824 | if (input == NULL) { 1825 | sprintf(buf, "Cannot open '%s' for input", fname); 1826 | message(1, buf); 1827 | return; 1828 | } 1829 | if (length == SIZE_MAX) { 1830 | fseek(input, 0, SEEK_END); 1831 | length = ftell(input) - offset; 1832 | } 1833 | fseek(input, offset, SEEK_SET); 1834 | #ifdef DEBUG 1835 | fprintf(stderr, "DEBUG: offset=%ld, length=%ld\n", offset, length); 1836 | #endif 1837 | while (length > 0) { 1838 | if (length > sizeof(buf)) { 1839 | size = sizeof(buf); 1840 | } else { 1841 | size = length; 1842 | } 1843 | size = fread(buf, 1, size, input); 1844 | if (size == 0) { 1845 | sprintf(buf, "File '%s' shorter than required length", fname); 1846 | message(1, buf); 1847 | break; 1848 | } 1849 | length -= size; 1850 | for (i = 0; i < size; i++) { 1851 | emit_byte(buf[i]); 1852 | } 1853 | } 1854 | fclose(input); 1855 | } 1856 | 1857 | /* 1858 | ** Do an assembler step 1859 | */ 1860 | void do_assembly(char *fname) 1861 | { 1862 | FILE *input; 1863 | char *p2; 1864 | char *p3; 1865 | char *pfname; 1866 | int level; 1867 | int avoid_level; 1868 | int times; 1869 | int base; 1870 | int pline; 1871 | int include; 1872 | int align; 1873 | long int offset; 1874 | size_t length; 1875 | 1876 | input = fopen(fname, "r"); 1877 | if (input == NULL) { 1878 | fprintf(stderr, "Error: cannot open '%s' for input\n", fname); 1879 | errors++; 1880 | return; 1881 | } 1882 | 1883 | pfname = input_filename; 1884 | pline = line_number; 1885 | input_filename = fname; 1886 | level = 0; 1887 | avoid_level = -1; 1888 | global_label[0] = '\0'; 1889 | line_number = 0; 1890 | base = 0; 1891 | while (fgets(line, sizeof(line), input)) { 1892 | line_number++; 1893 | p = line; 1894 | while (*p) { 1895 | if (*p == '\'' && *(p - 1) != '\\') { 1896 | p++; 1897 | while (*p && *p != '\'' && *(p - 1) != '\\') 1898 | p++; 1899 | } else if (*p == '"' && *(p - 1) != '\\') { 1900 | p++; 1901 | while (*p && *p != '"' && *(p - 1) != '\\') 1902 | p++; 1903 | } else if (*p == ';') { 1904 | while (*p) 1905 | p++; 1906 | break; 1907 | } 1908 | *p = toupper(*p); 1909 | p++; 1910 | } 1911 | if (p > line && *(p - 1) == '\n') 1912 | p--; 1913 | if (p > line && *(p - 1) == '\r') 1914 | p--; 1915 | *p = '\0'; 1916 | 1917 | base = address; 1918 | g = generated; 1919 | include = 0; 1920 | 1921 | while (1) { 1922 | p = line; 1923 | separate(); 1924 | if (part[0] == '\0' && (*p == '\0' || *p == ';')) /* Empty line */ 1925 | break; 1926 | if (part[0] != '\0' && part[strlen(part) - 1] == ':') { /* Label */ 1927 | part[strlen(part) - 1] = '\0'; 1928 | if (part[0] == '.') { 1929 | strcpy(name, global_label); 1930 | strcat(name, part); 1931 | } else { 1932 | strcpy(name, part); 1933 | strcpy(global_label, name); 1934 | } 1935 | separate(); 1936 | if (avoid_level == -1 || level < avoid_level) { 1937 | if (strcmp(part, "EQU") == 0) { 1938 | p2 = match_expression(p, &instruction_value); 1939 | if (p2 == NULL) { 1940 | message(1, "bad expression"); 1941 | } else { 1942 | if (assembler_step == 1) { 1943 | if (building_jumps) { 1944 | if (find_label(name)) { 1945 | char m[18 + MAX_SIZE]; 1946 | 1947 | sprintf(m, "Redefined label '%s'", name); 1948 | message(1, m); 1949 | } else { 1950 | last_label = define_label(name, instruction_value); 1951 | } 1952 | } else { 1953 | last_label = find_label(name); 1954 | if (last_label == NULL) { 1955 | fprintf(stderr, "Error: label not found before '%s'\n", name); 1956 | exit(1); 1957 | } 1958 | last_label->value = instruction_value; 1959 | } 1960 | } else { 1961 | last_label = find_label(name); 1962 | if (last_label == NULL) { 1963 | char m[33 + MAX_SIZE]; 1964 | 1965 | sprintf(m, "Inconsistency, label '%s' not found", name); 1966 | message(1, m); 1967 | } else { 1968 | if (last_label->value != instruction_value) { 1969 | #ifdef DEBUG 1970 | fprintf(stderr, "Woops: label '%s' changed value from %04x to %04x\n", last_label->name, last_label->value, instruction_value); 1971 | #endif 1972 | change = 1; 1973 | } 1974 | last_label->value = instruction_value; 1975 | } 1976 | } 1977 | check_end(p2); 1978 | } 1979 | break; 1980 | } 1981 | if (first_time == 1) { 1982 | #ifdef DEBUG 1983 | fprintf(stderr, "First time '%s' at line %d\n", line, line_number); 1984 | #endif 1985 | first_time = 0; 1986 | reset_address(); 1987 | } 1988 | if (assembler_step == 1) { 1989 | if (building_jumps) { 1990 | if (find_label(name)) { 1991 | char m[18 + MAX_SIZE]; 1992 | 1993 | sprintf(m, "Redefined label '%s'", name); 1994 | message(1, m); 1995 | } else { 1996 | last_label = define_label(name, address); 1997 | } 1998 | } else { 1999 | last_label = find_label(name); 2000 | if (last_label == NULL) { 2001 | fprintf(stderr, "Error: label not found before '%s'\n", name); 2002 | exit(1); 2003 | } 2004 | last_label->value = address; 2005 | } 2006 | } else { 2007 | last_label = find_label(name); 2008 | if (last_label == NULL) { 2009 | char m[33 + MAX_SIZE]; 2010 | 2011 | sprintf(m, "Inconsistency, label '%s' not found", name); 2012 | message(1, m); 2013 | } else { 2014 | if (last_label->value != address) { 2015 | #ifdef DEBUG 2016 | fprintf(stderr, "Woops: label '%s' changed value from %04x to %04x\n", last_label->name, last_label->value, address); 2017 | #endif 2018 | change = 1; 2019 | } 2020 | last_label->value = address; 2021 | } 2022 | 2023 | } 2024 | } 2025 | } 2026 | if (strcmp(part, "IF") == 0) { 2027 | level++; 2028 | if (avoid_level != -1 && level >= avoid_level) 2029 | break; 2030 | undefined = 0; 2031 | p = match_expression(p, &instruction_value); 2032 | if (p == NULL) { 2033 | message(1, "Bad expression"); 2034 | } else if (undefined) { 2035 | message(1, "Undefined labels"); 2036 | } 2037 | if (instruction_value != 0) { 2038 | ; 2039 | } else { 2040 | avoid_level = level; 2041 | } 2042 | check_end(p); 2043 | break; 2044 | } 2045 | if (strcmp(part, "IFDEF") == 0) { 2046 | level++; 2047 | if (avoid_level != -1 && level >= avoid_level) 2048 | break; 2049 | separate(); 2050 | if (find_label(part) != NULL) { 2051 | ; 2052 | } else { 2053 | avoid_level = level; 2054 | } 2055 | check_end(p); 2056 | break; 2057 | } 2058 | if (strcmp(part, "IFNDEF") == 0) { 2059 | level++; 2060 | if (avoid_level != -1 && level >= avoid_level) 2061 | break; 2062 | separate(); 2063 | if (find_label(part) == NULL) { 2064 | ; 2065 | } else { 2066 | avoid_level = level; 2067 | } 2068 | check_end(p); 2069 | break; 2070 | } 2071 | if (strcmp(part, "ELSE") == 0) { 2072 | if (avoid_level != -1 && level > avoid_level) 2073 | break; 2074 | if (avoid_level == level) { 2075 | avoid_level = -1; 2076 | } else if (avoid_level == -1) { 2077 | avoid_level = level; 2078 | } 2079 | check_end(p); 2080 | break; 2081 | } 2082 | if (strcmp(part, "ENDIF") == 0) { 2083 | if (avoid_level == level) 2084 | avoid_level = -1; 2085 | level--; 2086 | check_end(p); 2087 | break; 2088 | } 2089 | if (avoid_level != -1 && level >= avoid_level) { 2090 | #ifdef DEBUG 2091 | fprintf(stderr, "Avoiding '%s'\n", line); 2092 | #endif 2093 | break; 2094 | } 2095 | if (strcmp(part, "CPU") == 0) { 2096 | separate(); 2097 | check_end(p); 2098 | if (strcmp(part, "Z80") == 0) { 2099 | processor = CPU_Z80; 2100 | } else if (strcmp(part, "6502") == 0) { 2101 | processor = CPU_6502; 2102 | } else { 2103 | message(1, "Unsupported processor requested"); 2104 | } 2105 | break; 2106 | } 2107 | if (strcmp(part, "INCLUDE") == 0) { 2108 | separate(); 2109 | check_end(p); 2110 | if (part[0] != '"' || part[strlen(part) - 1] != '"') { 2111 | message(1, "Missing quotes on include"); 2112 | break; 2113 | } 2114 | include = 1; 2115 | break; 2116 | } 2117 | if (strcmp(part, "INCBIN") == 0) { 2118 | p = avoid_spaces(p); 2119 | if (*p != '"') { 2120 | message(1, "Missing quotes on incbin"); 2121 | break; 2122 | } 2123 | p++; 2124 | p2 = included_file; 2125 | while (*p && *p != '"') { 2126 | if (*p == '\\') { 2127 | p++; 2128 | if (*p) 2129 | *p2++ = *p++; 2130 | } 2131 | *p2++ = *p++; 2132 | } 2133 | *p2 = '\0'; 2134 | if (*p != '"') { 2135 | message(1, "Missing quotes on incbin"); 2136 | break; 2137 | } 2138 | p++; 2139 | p = avoid_spaces(p); 2140 | offset = 0; 2141 | length = SIZE_MAX; 2142 | if (*p == ',') { 2143 | p++; 2144 | p = avoid_spaces(p); 2145 | undefined = 0; 2146 | p2 = match_expression(p, &instruction_value); 2147 | if (p2 == NULL) { 2148 | message(1, "Bad expression"); 2149 | } else if (undefined) { 2150 | message(1, "Cannot use undefined labels"); 2151 | } else { 2152 | offset = instruction_value; 2153 | p = avoid_spaces(p2); 2154 | if (*p == ',') { 2155 | p++; 2156 | p = avoid_spaces(p); 2157 | undefined = 0; 2158 | p2 = match_expression(p, &instruction_value); 2159 | if (p2 == NULL) { 2160 | message(1, "Bad expression"); 2161 | } else if (undefined) { 2162 | message(1, "Cannot use undefined labels"); 2163 | } else { 2164 | length = instruction_value; 2165 | p = p2; 2166 | } 2167 | } 2168 | } 2169 | } 2170 | check_end(p); 2171 | include = 2; 2172 | break; 2173 | } 2174 | if (strcmp(part, "ORG") == 0) { 2175 | p = avoid_spaces(p); 2176 | undefined = 0; 2177 | p2 = match_expression(p, &instruction_value); 2178 | if (p2 == NULL) { 2179 | message(1, "Bad expression"); 2180 | } else if (undefined) { 2181 | message(1, "Cannot use undefined labels"); 2182 | } else { 2183 | if (first_time == 1) { 2184 | first_time = 0; 2185 | start_address = instruction_value; 2186 | base = instruction_value; 2187 | } 2188 | address = instruction_value; 2189 | /* 2190 | ** Notice it cannot change output_address here 2191 | ** because it could require filling it to get to 2192 | ** the address. 2193 | */ 2194 | check_end(p2); 2195 | } 2196 | break; 2197 | } 2198 | if (strcmp(part, "FORG") == 0) { 2199 | p = avoid_spaces(p); 2200 | undefined = 0; 2201 | p2 = match_expression(p, &instruction_value); 2202 | if (p2 == NULL) { 2203 | message(1, "Bad expression"); 2204 | } else if (undefined) { 2205 | message(1, "Cannot use undefined labels"); 2206 | } else { 2207 | if (assembler_step == 2) 2208 | fseek(output, instruction_value, SEEK_SET); 2209 | first_time = 1; 2210 | output_address = -1; /* Avoid unnecessary filling */ 2211 | check_end(p2); 2212 | } 2213 | break; 2214 | } 2215 | if (strcmp(part, "ALIGN") == 0) { 2216 | p = avoid_spaces(p); 2217 | undefined = 0; 2218 | p2 = match_expression(p, &instruction_value); 2219 | if (p2 == NULL) { 2220 | message(1, "Bad expression"); 2221 | } else if (undefined) { 2222 | message(1, "Cannot use undefined labels"); 2223 | } else { 2224 | align = address / instruction_value; 2225 | align = align * instruction_value; 2226 | align = align + instruction_value; 2227 | while (address < align) 2228 | emit_byte(0x00); 2229 | check_end(p2); 2230 | } 2231 | break; 2232 | } 2233 | if (first_time == 1) { 2234 | #ifdef DEBUG 2235 | fprintf(stderr, "First time '%s' at line %d\n", line, line_number); 2236 | #endif 2237 | first_time = 0; 2238 | reset_address(); 2239 | } 2240 | times = 1; 2241 | if (strcmp(part, "TIMES") == 0) { 2242 | undefined = 0; 2243 | p2 = match_expression(p, &instruction_value); 2244 | if (p2 == NULL) { 2245 | message(1, "bad expression"); 2246 | break; 2247 | } 2248 | if (undefined) { 2249 | message(1, "non-constant expression"); 2250 | break; 2251 | } 2252 | if (instruction_value < 0) { 2253 | char buffer[256]; 2254 | 2255 | sprintf(buffer, "negative value (%d) for TIMES", instruction_value); 2256 | message(1, buffer); 2257 | break; 2258 | } 2259 | times = instruction_value; 2260 | p = p2; 2261 | separate(); 2262 | } 2263 | base = address; 2264 | g = generated; 2265 | p3 = prev_p; 2266 | while (times) { 2267 | p = p3; 2268 | separate(); 2269 | process_instruction(); 2270 | times--; 2271 | } 2272 | break; 2273 | } 2274 | if (assembler_step == 2 && listing != NULL) { 2275 | if (first_time) 2276 | fprintf(listing, " "); 2277 | else 2278 | fprintf(listing, "%04X ", base); 2279 | p = generated; 2280 | while (p < g) { 2281 | fprintf(listing, "%02X", *p++ & 255); 2282 | } 2283 | while (p < generated + sizeof(generated)) { 2284 | fprintf(listing, " "); 2285 | p++; 2286 | } 2287 | fprintf(listing, " %05d %s\n", line_number, line); 2288 | } 2289 | if (include == 1) { 2290 | part[strlen(part) - 1] = '\0'; 2291 | do_assembly(part + 1); 2292 | } 2293 | if (include == 2) { 2294 | part[strlen(part) - 1] = '\0'; 2295 | incbin(included_file, offset, length); 2296 | } 2297 | } 2298 | fclose(input); 2299 | line_number = pline; 2300 | input_filename = pfname; 2301 | } 2302 | 2303 | /* 2304 | ** Main program 2305 | */ 2306 | int main(int argc, char *argv[]) 2307 | { 2308 | int c; 2309 | int d; 2310 | char *p; 2311 | char *ifname; 2312 | int sms_checksum; 2313 | 2314 | /* 2315 | ** If ran without arguments then show usage 2316 | */ 2317 | if (argc == 1) { 2318 | fprintf(stderr, "Typical usage:\n"); 2319 | fprintf(stderr, "gasm80 game.asm -o game.rom\n"); 2320 | fprintf(stderr, "gasm80 game.asm -o game.rom -l game.lst\n"); 2321 | fprintf(stderr, "gasm80 game.asm -o game.rom -l game.lst -s game.sym\n"); 2322 | fprintf(stderr, "gasm80 game.asm -o game.rom -sms\n"); 2323 | exit(1); 2324 | } 2325 | 2326 | /* 2327 | ** Start to collect arguments 2328 | */ 2329 | ifname = NULL; 2330 | output_filename = NULL; 2331 | listing_filename = NULL; 2332 | symbol_filename = NULL; 2333 | default_start_address = 0; 2334 | sms_checksum = 0; 2335 | c = 1; 2336 | while (c < argc) { 2337 | if (argv[c][0] == '-') { /* All arguments start with dash */ 2338 | d = tolower(argv[c][1]); 2339 | if (d == 's' && tolower(argv[c][2]) == 'm' && tolower(argv[c][3]) == 's' && argv[c][4] == '\0') { 2340 | c++; 2341 | sms_checksum = 1; 2342 | } else if (d == 'f') { /* Format */ 2343 | c++; 2344 | if (c >= argc) { 2345 | fprintf(stderr, "Error: no argument for -f\n"); 2346 | exit(1); 2347 | } else { 2348 | to_lowercase(argv[c]); 2349 | if (strcmp(argv[c], "bin") == 0) { 2350 | default_start_address = 0; 2351 | } else if (strcmp(argv[c], "com") == 0) { 2352 | default_start_address = 0x0100; 2353 | } else { 2354 | fprintf(stderr, "Error: only 'bin', 'com' supported for -f (it is '%s')\n", argv[c]); 2355 | exit(1); 2356 | } 2357 | c++; 2358 | } 2359 | } else if (d == 'o') { /* Object file name */ 2360 | c++; 2361 | if (c >= argc) { 2362 | fprintf(stderr, "Error: no argument for -o\n"); 2363 | exit(1); 2364 | } else if (output_filename != NULL) { 2365 | fprintf(stderr, "Error: already a -o argument is present\n"); 2366 | exit(1); 2367 | } else { 2368 | output_filename = argv[c]; 2369 | c++; 2370 | } 2371 | } else if (d == 'l') { /* Listing file name */ 2372 | c++; 2373 | if (c >= argc) { 2374 | fprintf(stderr, "Error: no argument for -l\n"); 2375 | exit(1); 2376 | } else if (listing_filename != NULL) { 2377 | fprintf(stderr, "Error: already a -l argument is present\n"); 2378 | exit(1); 2379 | } else { 2380 | listing_filename = argv[c]; 2381 | c++; 2382 | } 2383 | } else if (d == 's') { /* Symbol file name */ 2384 | c++; 2385 | if (c >= argc) { 2386 | fprintf(stderr, "Error: no argument for -s\n"); 2387 | exit(1); 2388 | } else if (symbol_filename != NULL) { 2389 | fprintf(stderr, "Error: already a -s argument is present\n"); 2390 | exit(1); 2391 | } else { 2392 | symbol_filename = argv[c]; 2393 | c++; 2394 | } 2395 | } else if (d == 'd') { /* Define label */ 2396 | p = argv[c] + 2; 2397 | while (*p && *p != '=') { 2398 | *p = toupper(*p); 2399 | p++; 2400 | } 2401 | if (*p == '=') { 2402 | *p++ = 0; 2403 | undefined = 0; 2404 | p = match_expression(p, &instruction_value); 2405 | if (p == NULL) { 2406 | fprintf(stderr, "Error: wrong label definition\n"); 2407 | exit(1); 2408 | } else if (undefined) { 2409 | fprintf(stderr, "Error: non-constant label definition\n"); 2410 | exit(1); 2411 | } else { 2412 | define_label(argv[c] + 2, instruction_value); 2413 | } 2414 | } 2415 | c++; 2416 | } else { 2417 | fprintf(stderr, "Error: unknown argument %s\n", argv[c]); 2418 | exit(1); 2419 | } 2420 | } else { 2421 | if (ifname != NULL) { 2422 | fprintf(stderr, "Error: more than one input file name: %s\n", argv[c]); 2423 | exit(1); 2424 | } else { 2425 | ifname = argv[c]; 2426 | } 2427 | c++; 2428 | } 2429 | } 2430 | 2431 | if (ifname == NULL) { 2432 | fprintf(stderr, "No input filename provided\n"); 2433 | exit(1); 2434 | } 2435 | 2436 | /* 2437 | ** Do first step of assembly 2438 | */ 2439 | 2440 | first_jump = NULL; 2441 | current_jump = NULL; 2442 | last_jump = NULL; 2443 | building_jumps = 1; 2444 | 2445 | assembler_step = 1; 2446 | first_time = 1; 2447 | processor = CPU_Z80; 2448 | do_assembly(ifname); 2449 | 2450 | if (!errors) { 2451 | if (first_jump != NULL) { 2452 | fprintf(stderr, "Expanding jumps as needed for 6502: "); 2453 | } 2454 | while (!errors && first_jump != NULL) { /* This will happen only for 6502 CPUs */ 2455 | int all_good; 2456 | int c; 2457 | 2458 | fprintf(stderr, "."); 2459 | 2460 | building_jumps = 0; 2461 | current_jump = first_jump; 2462 | assembler_step = 1; 2463 | first_time = 1; 2464 | processor = CPU_Z80; 2465 | do_assembly(ifname); 2466 | 2467 | all_good = 1; 2468 | current_jump = first_jump; 2469 | while (current_jump != NULL) { 2470 | if (current_jump->relative) { 2471 | c = current_jump->target - (current_jump->address + 2); 2472 | if (c < - 128 || c > 127) { 2473 | current_jump->relative = 0; /* Expand the relative jump to rel.jump+abs.jump */ 2474 | all_good = 0; 2475 | } 2476 | } 2477 | current_jump = current_jump->next; 2478 | } 2479 | if (all_good) 2480 | break; 2481 | 2482 | building_jumps = 0; 2483 | current_jump = first_jump; 2484 | assembler_step = 1; 2485 | first_time = 1; 2486 | processor = CPU_Z80; 2487 | do_assembly(ifname); 2488 | } 2489 | if (!errors && first_jump != NULL) { 2490 | fprintf(stderr, " Done!\n"); 2491 | } 2492 | } 2493 | 2494 | if (!errors) { 2495 | 2496 | /* 2497 | ** Do second step of assembly and generate final output 2498 | */ 2499 | if (output_filename == NULL) { 2500 | fprintf(stderr, "No output filename provided\n"); 2501 | exit(1); 2502 | } 2503 | change_number = 0; 2504 | do { 2505 | change = 0; 2506 | if (listing_filename != NULL) { 2507 | listing = fopen(listing_filename, "w"); 2508 | if (listing == NULL) { 2509 | fprintf(stderr, "Error: couldn't open '%s' as listing file\n", output_filename); 2510 | exit(1); 2511 | } 2512 | } 2513 | if (symbol_filename != NULL) { 2514 | symbol = fopen(symbol_filename, "w"); 2515 | if (symbol == NULL) { 2516 | fprintf(stderr, "Error: couldn't open '%s' as symbol file\n", symbol_filename); 2517 | exit(1); 2518 | } 2519 | } 2520 | output = fopen(output_filename, "w+b"); 2521 | if (output == NULL) { 2522 | fprintf(stderr, "Error: couldn't open '%s' as output file\n", output_filename); 2523 | exit(1); 2524 | } 2525 | assembler_step = 2; 2526 | first_time = 1; 2527 | output_address = -1; 2528 | building_jumps = 0; 2529 | current_jump = first_jump; 2530 | do_assembly(ifname); 2531 | 2532 | if (change == 0) { 2533 | if (listing != NULL) { 2534 | fprintf(listing, "\n%05d ERRORS FOUND\n", errors); 2535 | fprintf(listing, "%05d WARNINGS FOUND\n\n", warnings); 2536 | fprintf(listing, "%05d PROGRAM BYTES\n\n", bytes); 2537 | } 2538 | if (label_list != NULL) { 2539 | if (listing != NULL) 2540 | fprintf(listing, "%-20s VALUE/ADDRESS\n\n", "LABEL"); 2541 | sort_labels(label_list); 2542 | } 2543 | } 2544 | if (sms_checksum) { 2545 | fseek(output, 0, SEEK_END); 2546 | c = ftell(output); 2547 | if (c >= 32768) { 2548 | fseek(output, 0, SEEK_SET); 2549 | c = 0; 2550 | for (d = 0; d < 0x7ff0; d++) 2551 | c = c + (fgetc(output) & 0xff); 2552 | fseek(output, 0x7ffa, SEEK_SET); 2553 | fputc(c & 0xff, output); 2554 | fputc((c >> 8) & 0xff, output); 2555 | } else { 2556 | fprintf(stderr, "Sega Master System: ROM less than 32KB, cannot generate checksum\n"); 2557 | } 2558 | } 2559 | fclose(output); 2560 | if (listing_filename != NULL) 2561 | fclose(listing); 2562 | if (symbol != NULL) 2563 | fclose(symbol); 2564 | if (change) { 2565 | change_number++; 2566 | if (change_number == 5) { 2567 | fprintf(stderr, "Aborted: Couldn't stabilize moving label\n"); 2568 | errors++; 2569 | } 2570 | } 2571 | if (errors) { 2572 | remove(output_filename); 2573 | if (listing_filename != NULL) 2574 | remove(listing_filename); 2575 | exit(1); 2576 | } 2577 | } while (change) ; 2578 | 2579 | exit(0); 2580 | } 2581 | 2582 | exit(1); 2583 | } 2584 | --------------------------------------------------------------------------------