1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * URASM Z80 assembler/disassembler core v0.0.0a
6 * This program is free software. It comes without any warranty, to
7 * the extent permitted by applicable law. You can redistribute it
8 * and/or modify it under the terms of the Do What The Fuck You Want
9 * To Public License, Version 2, as published by Sam Hocevar. See
10 * http://sam.zoy.org/wtfpl/COPYING for more details.
26 URFindLabelByAddr urFindLabelByAddr
= NULL
;
27 URFindLabelByName urFindLabelByName
= NULL
;
28 URGetByte urGetByte
= NULL
;
29 URPutByte urPutByte
= NULL
;
30 URIsLabelDefinedOrKnown urIsLabelDefinedOrKnown
= NULL
;
33 const char *URASM_TOKENS
[URASM_MAX_TOKEN
] = {
34 "ADC", "ADD", "AND", "BIT", "CALL","CCF", "CP", "CPD",
35 "CPDR","CPI", "CPIR","CPL", "DAA", "DEC", "DI", "DJNZ",
36 "EI", "EX", "EXX", "HALT","IM", "IN", "INC", "IND",
37 "INDR","INI", "INIR","JP", "JR", "LD", "LDD", "LDDR",
38 "LDI", "LDIR","NEG", "NOP", "OR", "OTDR","OTIR","OUT",
39 "OUTD","OUTI","POP", "PUSH","RES", "RET", "RETI","RETN",
40 "RL", "RLA", "RLC", "RLCA","RLD", "RR", "RRA", "RRC",
41 "RRCA","RRD", "RST", "SBC", "SCF", "SET", "SLA", "SLI",
42 "SLL", "SRA", "SRL", "SUB", "XOR", "XSLT","NOPX","NOPY"
46 const char *URA_REGS8
[8] = {"B","C","D","E","H","L","(HL)","A"};
47 const char *URA_REGS16
[4] = {"BC","DE","HL","SP"};
48 const char *URA_REGS16A
[4] = {"BC","DE","HL","AF"};
49 const char *URA_COND
[8] = {"NZ","Z","NC","C","PO","PE","P","M"};
52 // the longest matches must come first (for disassembler)
53 // solid-masked must come first (for disassembler)
54 // assembler searches the table from the last command
55 // disassembler searches the table from the first command
56 // heh, i spent a whole night creating this shit! %-)
57 const URAsmCmdInfo URASM_COMMANDS
[URASM_MAX_COMMAND
+1] = {
58 {.mnemo
=UT_NOPX
, .code
=0x000000DDUL
, .mask
=0x00000000UL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
59 {.mnemo
=UT_NOPY
, .code
=0x000000FDUL
, .mask
=0x00000000UL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
60 // DD/CB opcodes (special)
62 {.mnemo
=UT_RLC
, .code
=0x0600CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
64 {.mnemo
=UT_RRC
, .code
=0x0E00CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
66 {.mnemo
=UT_RL
, .code
=0x1600CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
68 {.mnemo
=UT_RR
, .code
=0x1E00CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
70 {.mnemo
=UT_SLA
, .code
=0x2600CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
72 {.mnemo
=UT_SRA
, .code
=0x2E00CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
74 {.mnemo
=UT_SLL
, .code
=0x3600CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
76 {.mnemo
=UT_SLI
, .code
=0x3600CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
78 {.mnemo
=UT_SRL
, .code
=0x3E00CBDDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
80 {.mnemo
=UT_RES
, .code
=0x8600CBDDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_NONE
}},
82 {.mnemo
=UT_SET
, .code
=0xC600CBDDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_NONE
}},
83 // FD/CB opcodes (special)
85 {.mnemo
=UT_RLC
, .code
=0x0600CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
87 {.mnemo
=UT_RRC
, .code
=0x0E00CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
89 {.mnemo
=UT_RL
, .code
=0x1600CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
91 {.mnemo
=UT_RR
, .code
=0x1E00CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
93 {.mnemo
=UT_SLA
, .code
=0x2600CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
95 {.mnemo
=UT_SRA
, .code
=0x2E00CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
97 {.mnemo
=UT_SLL
, .code
=0x3600CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
99 {.mnemo
=UT_SLI
, .code
=0x3600CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
101 {.mnemo
=UT_SRL
, .code
=0x3E00CBFDUL
, .mask
=0xFF00FFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
103 {.mnemo
=UT_RES
, .code
=0x8600CBFDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_NONE
}},
105 {.mnemo
=UT_SET
, .code
=0xC600CBFDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_NONE
}},
109 {.mnemo
=UT_RLC
, .code
=0x0000CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
111 {.mnemo
=UT_RRC
, .code
=0x0800CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
113 {.mnemo
=UT_RL
, .code
=0x1000CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
115 {.mnemo
=UT_RR
, .code
=0x1800CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
117 {.mnemo
=UT_SLA
, .code
=0x2000CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
119 {.mnemo
=UT_SRA
, .code
=0x2800CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
121 {.mnemo
=UT_SLL
, .code
=0x3000CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
123 {.mnemo
=UT_SLI
, .code
=0x3000CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
125 {.mnemo
=UT_SRL
, .code
=0x3800CBDDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
127 {.mnemo
=UT_BIT
, .code
=0x4600CBDDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_NONE
}},
129 {.mnemo
=UT_BIT
, .code
=0x4000CBDDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_R8_NOM
}},
131 {.mnemo
=UT_RES
, .code
=0x8000CBDDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_R8_NOM
}},
133 {.mnemo
=UT_SET
, .code
=0xC000CBDDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIX
, UO_R8_NOM
}},
136 {.mnemo
=UT_RLC
, .code
=0x0000CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
138 {.mnemo
=UT_RRC
, .code
=0x0800CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
140 {.mnemo
=UT_RL
, .code
=0x1000CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
142 {.mnemo
=UT_RR
, .code
=0x1800CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
144 {.mnemo
=UT_SLA
, .code
=0x2000CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
146 {.mnemo
=UT_SRA
, .code
=0x2800CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
148 {.mnemo
=UT_SLL
, .code
=0x3000CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
150 {.mnemo
=UT_SLI
, .code
=0x3000CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
152 {.mnemo
=UT_SRL
, .code
=0x3800CBFDUL
, .mask
=0xF800FFFFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
154 {.mnemo
=UT_BIT
, .code
=0x4600CBFDUL
, .mask
=0xC700FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_NONE
}},
156 {.mnemo
=UT_BIT
, .code
=0x4000CBFDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_R8_NOM
}},
158 {.mnemo
=UT_RES
, .code
=0x8000CBFDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_R8_NOM
}},
160 {.mnemo
=UT_SET
, .code
=0xC000CBFDUL
, .mask
=0xC000FFFFUL
, .ops
={UO_BITN
, UO_MIY
, UO_R8_NOM
}},
161 // standard CB opcodes
163 {.mnemo
=UT_RLC
, .code
=0x00CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
165 {.mnemo
=UT_RRC
, .code
=0x08CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
167 {.mnemo
=UT_RL
, .code
=0x10CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
169 {.mnemo
=UT_RR
, .code
=0x18CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
171 {.mnemo
=UT_SLA
, .code
=0x20CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
173 {.mnemo
=UT_SRA
, .code
=0x28CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
175 {.mnemo
=UT_SLL
, .code
=0x30CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
177 {.mnemo
=UT_SLI
, .code
=0x30CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
179 {.mnemo
=UT_SRL
, .code
=0x38CBUL
, .mask
=0xF8FFUL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
181 {.mnemo
=UT_BIT
, .code
=0x40CBUL
, .mask
=0xC0FFUL
, .ops
={UO_BITN
, UO_R8
, UO_NONE
}},
183 {.mnemo
=UT_RES
, .code
=0x80CBUL
, .mask
=0xC0FFUL
, .ops
={UO_BITN
, UO_R8
, UO_NONE
}},
185 {.mnemo
=UT_SET
, .code
=0xC0CBUL
, .mask
=0xC0FFUL
, .ops
={UO_BITN
, UO_R8
, UO_NONE
}},
189 {.mnemo
=UT_XSLT
, .code
=0xFBEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
190 // ED string instructions
191 {.mnemo
=UT_LDI
, .code
=0xA0EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
192 {.mnemo
=UT_LDIR
, .code
=0xB0EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
193 {.mnemo
=UT_CPI
, .code
=0xA1EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
194 {.mnemo
=UT_CPIR
, .code
=0xB1EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
195 {.mnemo
=UT_INI
, .code
=0xA2EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
196 {.mnemo
=UT_INIR
, .code
=0xB2EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
197 {.mnemo
=UT_OUTI
, .code
=0xA3EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
198 {.mnemo
=UT_OTIR
, .code
=0xB3EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
199 {.mnemo
=UT_LDD
, .code
=0xA8EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
200 {.mnemo
=UT_LDDR
, .code
=0xB8EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
201 {.mnemo
=UT_CPD
, .code
=0xA9EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
202 {.mnemo
=UT_CPDR
, .code
=0xB9EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
203 {.mnemo
=UT_IND
, .code
=0xAAEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
204 {.mnemo
=UT_INDR
, .code
=0xBAEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
205 {.mnemo
=UT_OUTD
, .code
=0xABEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
206 {.mnemo
=UT_OTDR
, .code
=0xBBEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
209 {.mnemo
=UT_RRD
, .code
=0x67EDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
210 {.mnemo
=UT_RLD
, .code
=0x6FEDUL
, .mask
=0xFFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
213 {.mnemo
=UT_IN
, .code
=0x70EDUL
, .mask
=0xFFFFUL
, .ops
={UO_PORTC
, UO_NONE
, UO_NONE
}},
215 {.mnemo
=UT_OUT
, .code
=0x71EDUL
, .mask
=0xFFFFUL
, .ops
={UO_PORTC
, UO_IM0
, UO_NONE
}},
218 {.mnemo
=UT_LD
, .code
=0x47EDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_I
, UO_R8_A
, UO_NONE
}},
220 {.mnemo
=UT_LD
, .code
=0x57EDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_I
, UO_NONE
}},
222 {.mnemo
=UT_LD
, .code
=0x4FEDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_R
, UO_R8_A
, UO_NONE
}},
224 {.mnemo
=UT_LD
, .code
=0x5FEDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_R
, UO_NONE
}},
226 //(.mnemo=UT_IM, .code=0x4EEDUL, .mask=0xFFFFUL, .ops={UO_IM01, UO_NONE, UO_NONE}},
229 {.mnemo
=UT_RETN
, .code
=0x45EDUL
, .mask
=0xCFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
230 {.mnemo
=UT_RETI
, .code
=0x4DEDUL
, .mask
=0xCFFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
233 {.mnemo
=UT_SBC
, .code
=0x42EDUL
, .mask
=0xCFFFUL
, .ops
={UO_R16HL
, UO_R16
, UO_NONE
}},
235 {.mnemo
=UT_ADC
, .code
=0x4AEDUL
, .mask
=0xCFFFUL
, .ops
={UO_R16HL
, UO_R16
, UO_NONE
}},
237 {.mnemo
=UT_LD
, .code
=0x43EDUL
, .mask
=0xCFFFUL
, .ops
={UO_MEM16
, UO_R16
, UO_NONE
}},
239 {.mnemo
=UT_LD
, .code
=0x4BEDUL
, .mask
=0xCFFFUL
, .ops
={UO_R16
, UO_MEM16
, UO_NONE
}},
242 {.mnemo
=UT_NEG
, .code
=0x44EDUL
, .mask
=0xC7FFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
245 {.mnemo
=UT_IN
, .code
=0x40EDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_PORTC
, UO_NONE
}},
247 {.mnemo
=UT_OUT
, .code
=0x41EDUL
, .mask
=0xC7FFUL
, .ops
={UO_PORTC
, UO_2R8_NOM
, UO_NONE
}},
250 {.mnemo
=UT_IM
, .code
=0x5EEDUL
, .mask
=0xDFFFUL
, .ops
={UO_IM2
, UO_NONE
, UO_NONE
}},
252 {.mnemo
=UT_IM
, .code
=0x56EDUL
, .mask
=0xDFFFUL
, .ops
={UO_IM1
, UO_NONE
, UO_NONE
}},
254 {.mnemo
=UT_IM
, .code
=0x46EDUL
, .mask
=0xD7FFUL
, .ops
={UO_IM0
, UO_NONE
, UO_NONE
}},
257 {.mnemo
=UT_LD
, .code
=0xF9DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16SP
, UO_R16IX
, UO_NONE
}},
259 {.mnemo
=UT_LD
, .code
=0xF9FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16SP
, UO_R16IY
, UO_NONE
}},
262 {.mnemo
=UT_EX
, .code
=0xE3DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MSP
, UO_R16IX
, UO_NONE
}},
263 // EX IX,(SP) (ditto)
264 {.mnemo
=UT_EX
, .code
=0xE3DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_MSP
, UO_NONE
}},
266 {.mnemo
=UT_EX
, .code
=0xE3FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MSP
, UO_R16IY
, UO_NONE
}},
267 // EX IY,(SP) (ditto)
268 {.mnemo
=UT_EX
, .code
=0xE3FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_MSP
, UO_NONE
}},
271 {.mnemo
=UT_JP
, .code
=0xE9DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX0
, UO_NONE
, UO_NONE
}},
273 {.mnemo
=UT_JP
, .code
=0xE9FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY0
, UO_NONE
, UO_NONE
}},
275 {.mnemo
=UT_JP
, .code
=0xE9DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_NONE
, UO_NONE
}},
277 {.mnemo
=UT_JP
, .code
=0xE9FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_NONE
, UO_NONE
}},
280 {.mnemo
=UT_POP
, .code
=0xE1DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_NONE
, UO_NONE
}},
282 {.mnemo
=UT_PUSH
, .code
=0xE5DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_NONE
, UO_NONE
}},
284 {.mnemo
=UT_POP
, .code
=0xE1FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_NONE
, UO_NONE
}},
286 {.mnemo
=UT_PUSH
, .code
=0xE5FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_NONE
, UO_NONE
}},
289 {.mnemo
=UT_ADD
, .code
=0x86DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
291 {.mnemo
=UT_ADD
, .code
=0x86DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
293 {.mnemo
=UT_ADC
, .code
=0x8EDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
295 {.mnemo
=UT_ADC
, .code
=0x8EDDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
297 {.mnemo
=UT_SUB
, .code
=0x96DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
299 {.mnemo
=UT_SUB
, .code
=0x96DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
301 {.mnemo
=UT_SBC
, .code
=0x9EDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
303 {.mnemo
=UT_SBC
, .code
=0x9EDDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
305 {.mnemo
=UT_AND
, .code
=0xA6DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
307 {.mnemo
=UT_AND
, .code
=0xA6DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
309 {.mnemo
=UT_XOR
, .code
=0xAEDDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
311 {.mnemo
=UT_XOR
, .code
=0xAEDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
313 {.mnemo
=UT_OR
, .code
=0xB6DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
315 {.mnemo
=UT_OR
, .code
=0xB6DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
317 {.mnemo
=UT_CP
, .code
=0xBEDDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
319 {.mnemo
=UT_CP
, .code
=0xBEDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIX
, UO_NONE
}},
321 {.mnemo
=UT_ADD
, .code
=0x86FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
323 {.mnemo
=UT_ADD
, .code
=0x86FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
325 {.mnemo
=UT_ADC
, .code
=0x8EFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
327 {.mnemo
=UT_ADC
, .code
=0x8EFDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
329 {.mnemo
=UT_SUB
, .code
=0x96FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
331 {.mnemo
=UT_SUB
, .code
=0x96FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
333 {.mnemo
=UT_SBC
, .code
=0x9EFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
335 {.mnemo
=UT_SBC
, .code
=0x9EFDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
337 {.mnemo
=UT_AND
, .code
=0xA6FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
339 {.mnemo
=UT_AND
, .code
=0xA6FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
341 {.mnemo
=UT_XOR
, .code
=0xAEFDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
343 {.mnemo
=UT_XOR
, .code
=0xAEFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
345 {.mnemo
=UT_OR
, .code
=0xB6FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
347 {.mnemo
=UT_OR
, .code
=0xB6FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
349 {.mnemo
=UT_CP
, .code
=0xBEFDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
351 {.mnemo
=UT_CP
, .code
=0xBEFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_MIY
, UO_NONE
}},
353 {.mnemo
=UT_ADD
, .code
=0x84DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
355 {.mnemo
=UT_ADD
, .code
=0x84DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
357 {.mnemo
=UT_ADC
, .code
=0x8CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
359 {.mnemo
=UT_ADC
, .code
=0x8CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
361 {.mnemo
=UT_SUB
, .code
=0x94DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
363 {.mnemo
=UT_SUB
, .code
=0x94DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
365 {.mnemo
=UT_SBC
, .code
=0x9CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
367 {.mnemo
=UT_SBC
, .code
=0x9CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
369 {.mnemo
=UT_AND
, .code
=0xA4DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
371 {.mnemo
=UT_AND
, .code
=0xA4DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
373 {.mnemo
=UT_XOR
, .code
=0xACDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
375 {.mnemo
=UT_XOR
, .code
=0xACDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
377 {.mnemo
=UT_OR
, .code
=0xB4DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
379 {.mnemo
=UT_OR
, .code
=0xB4DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
381 {.mnemo
=UT_CP
, .code
=0xBCDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
383 {.mnemo
=UT_CP
, .code
=0xBCDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XH
, UO_NONE
}},
385 {.mnemo
=UT_ADD
, .code
=0x85DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
387 {.mnemo
=UT_ADD
, .code
=0x85DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
389 {.mnemo
=UT_ADC
, .code
=0x8DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
391 {.mnemo
=UT_ADC
, .code
=0x8DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
393 {.mnemo
=UT_SUB
, .code
=0x95DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
395 {.mnemo
=UT_SUB
, .code
=0x95DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
397 {.mnemo
=UT_SBC
, .code
=0x9DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
399 {.mnemo
=UT_SBC
, .code
=0x9DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
401 {.mnemo
=UT_AND
, .code
=0xA5DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
403 {.mnemo
=UT_AND
, .code
=0xA5DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
405 {.mnemo
=UT_XOR
, .code
=0xADDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
407 {.mnemo
=UT_XOR
, .code
=0xADDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
409 {.mnemo
=UT_OR
, .code
=0xB5DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
411 {.mnemo
=UT_OR
, .code
=0xB5DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
413 {.mnemo
=UT_CP
, .code
=0xBDDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
415 {.mnemo
=UT_CP
, .code
=0xBDDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_XL
, UO_NONE
}},
417 {.mnemo
=UT_ADD
, .code
=0x84FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
419 {.mnemo
=UT_ADD
, .code
=0x84FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
421 {.mnemo
=UT_ADC
, .code
=0x8CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
423 {.mnemo
=UT_ADC
, .code
=0x8CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
425 {.mnemo
=UT_SUB
, .code
=0x94FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
427 {.mnemo
=UT_SUB
, .code
=0x94FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
429 {.mnemo
=UT_SBC
, .code
=0x9CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
431 {.mnemo
=UT_SBC
, .code
=0x9CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
433 {.mnemo
=UT_AND
, .code
=0xA4FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
435 {.mnemo
=UT_AND
, .code
=0xA4FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
437 {.mnemo
=UT_XOR
, .code
=0xACFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
439 {.mnemo
=UT_XOR
, .code
=0xACFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
441 {.mnemo
=UT_OR
, .code
=0xB4FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
443 {.mnemo
=UT_OR
, .code
=0xB4FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
445 {.mnemo
=UT_CP
, .code
=0xBCFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
447 {.mnemo
=UT_CP
, .code
=0xBCFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YH
, UO_NONE
}},
449 {.mnemo
=UT_ADD
, .code
=0x85FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
451 {.mnemo
=UT_ADD
, .code
=0x85FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
453 {.mnemo
=UT_ADC
, .code
=0x8DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
455 {.mnemo
=UT_ADC
, .code
=0x8DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
457 {.mnemo
=UT_SUB
, .code
=0x95FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
459 {.mnemo
=UT_SUB
, .code
=0x95FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
461 {.mnemo
=UT_SBC
, .code
=0x9DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
463 {.mnemo
=UT_SBC
, .code
=0x9DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
465 {.mnemo
=UT_AND
, .code
=0xA5FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
467 {.mnemo
=UT_AND
, .code
=0xA5FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
469 {.mnemo
=UT_XOR
, .code
=0xADFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
471 {.mnemo
=UT_XOR
, .code
=0xADFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
473 {.mnemo
=UT_OR
, .code
=0xB5FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
475 {.mnemo
=UT_OR
, .code
=0xB5FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
477 {.mnemo
=UT_CP
, .code
=0xBDFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
479 {.mnemo
=UT_CP
, .code
=0xBDFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_A
, UO_R8_YL
, UO_NONE
}},
482 {.mnemo
=UT_LD
, .code
=0x64DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_R8_XH
, UO_NONE
}},
484 {.mnemo
=UT_LD
, .code
=0x65DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_R8_XL
, UO_NONE
}},
486 {.mnemo
=UT_LD
, .code
=0x6CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_R8_XH
, UO_NONE
}},
488 {.mnemo
=UT_LD
, .code
=0x6DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_R8_XL
, UO_NONE
}},
490 {.mnemo
=UT_LD
, .code
=0x64FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_R8_YH
, UO_NONE
}},
492 {.mnemo
=UT_LD
, .code
=0x65FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_R8_YL
, UO_NONE
}},
494 {.mnemo
=UT_LD
, .code
=0x6CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_R8_YH
, UO_NONE
}},
496 {.mnemo
=UT_LD
, .code
=0x6DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_R8_YL
, UO_NONE
}},
499 {.mnemo
=UT_LD
, .code
=0x22DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MEM16
, UO_R16IX
, UO_NONE
}},
501 {.mnemo
=UT_LD
, .code
=0x2ADDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_MEM16
, UO_NONE
}},
503 {.mnemo
=UT_LD
, .code
=0x22FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MEM16
, UO_R16IY
, UO_NONE
}},
505 {.mnemo
=UT_LD
, .code
=0x2AFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_MEM16
, UO_NONE
}},
508 {.mnemo
=UT_LD
, .code
=0x21DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_IMM16
, UO_NONE
}},
510 {.mnemo
=UT_LD
, .code
=0x21FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_IMM16
, UO_NONE
}},
513 {.mnemo
=UT_INC
, .code
=0x23DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_NONE
, UO_NONE
}},
515 {.mnemo
=UT_DEC
, .code
=0x2BDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_NONE
, UO_NONE
}},
517 {.mnemo
=UT_INC
, .code
=0x23FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_NONE
, UO_NONE
}},
519 {.mnemo
=UT_DEC
, .code
=0x2BFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_NONE
, UO_NONE
}},
522 {.mnemo
=UT_INC
, .code
=0x34DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
524 {.mnemo
=UT_DEC
, .code
=0x35DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_NONE
, UO_NONE
}},
526 {.mnemo
=UT_LD
, .code
=0x36DDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIX
, UO_IMM8
, UO_NONE
}},
528 {.mnemo
=UT_INC
, .code
=0x34FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
530 {.mnemo
=UT_DEC
, .code
=0x35FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_NONE
, UO_NONE
}},
532 {.mnemo
=UT_LD
, .code
=0x36FDUL
, .mask
=0xFFFFUL
, .ops
={UO_MIY
, UO_IMM8
, UO_NONE
}},
535 {.mnemo
=UT_INC
, .code
=0x24DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
537 {.mnemo
=UT_DEC
, .code
=0x25DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_NONE
, UO_NONE
}},
539 {.mnemo
=UT_INC
, .code
=0x2CDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
541 {.mnemo
=UT_DEC
, .code
=0x2DDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_NONE
, UO_NONE
}},
543 {.mnemo
=UT_INC
, .code
=0x24FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
545 {.mnemo
=UT_DEC
, .code
=0x25FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_NONE
, UO_NONE
}},
547 {.mnemo
=UT_INC
, .code
=0x2CFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
549 {.mnemo
=UT_DEC
, .code
=0x2DFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_NONE
, UO_NONE
}},
552 {.mnemo
=UT_LD
, .code
=0x26DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XH
, UO_IMM8
, UO_NONE
}},
554 {.mnemo
=UT_LD
, .code
=0x2EDDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_XL
, UO_IMM8
, UO_NONE
}},
556 {.mnemo
=UT_LD
, .code
=0x26FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YH
, UO_IMM8
, UO_NONE
}},
558 {.mnemo
=UT_LD
, .code
=0x2EFDUL
, .mask
=0xFFFFUL
, .ops
={UO_R8_YL
, UO_IMM8
, UO_NONE
}},
561 {.mnemo
=UT_ADD
, .code
=0x09DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_R16BC
, UO_NONE
}},
563 {.mnemo
=UT_ADD
, .code
=0x19DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_R16DE
, UO_NONE
}},
565 {.mnemo
=UT_ADD
, .code
=0x29DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_R16IX
, UO_NONE
}},
567 {.mnemo
=UT_ADD
, .code
=0x39DDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IX
, UO_R16SP
, UO_NONE
}},
569 {.mnemo
=UT_ADD
, .code
=0x09FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_R16BC
, UO_NONE
}},
571 {.mnemo
=UT_ADD
, .code
=0x19FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_R16DE
, UO_NONE
}},
573 {.mnemo
=UT_ADD
, .code
=0x29FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_R16IY
, UO_NONE
}},
575 {.mnemo
=UT_ADD
, .code
=0x39FDUL
, .mask
=0xFFFFUL
, .ops
={UO_R16IY
, UO_R16SP
, UO_NONE
}},
578 {.mnemo
=UT_LD
, .code
=0x60DDUL
, .mask
=0xF8FFUL
, .ops
={UO_R8_XH
, UO_R8_NOM
, UO_NONE
}},
580 {.mnemo
=UT_LD
, .code
=0x68DDUL
, .mask
=0xF8FFUL
, .ops
={UO_R8_XL
, UO_R8_NOM
, UO_NONE
}},
582 {.mnemo
=UT_LD
, .code
=0x70DDUL
, .mask
=0xF8FFUL
, .ops
={UO_MIX
, UO_R8_NOM
, UO_NONE
}},
584 {.mnemo
=UT_LD
, .code
=0x60FDUL
, .mask
=0xF8FFUL
, .ops
={UO_R8_YH
, UO_R8_NOM
, UO_NONE
}},
586 {.mnemo
=UT_LD
, .code
=0x68FDUL
, .mask
=0xF8FFUL
, .ops
={UO_R8_YL
, UO_R8_NOM
, UO_NONE
}},
588 {.mnemo
=UT_LD
, .code
=0x70FDUL
, .mask
=0xF8FFUL
, .ops
={UO_MIY
, UO_R8_NOM
, UO_NONE
}},
591 {.mnemo
=UT_LD
, .code
=0x44DDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_R8_XH
, UO_NONE
}},
593 {.mnemo
=UT_LD
, .code
=0x45DDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_R8_XL
, UO_NONE
}},
595 {.mnemo
=UT_LD
, .code
=0x46DDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_MIX
, UO_NONE
}},
598 {.mnemo
=UT_LD
, .code
=0x44FDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_R8_YH
, UO_NONE
}},
600 {.mnemo
=UT_LD
, .code
=0x45FDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_R8_YL
, UO_NONE
}},
602 {.mnemo
=UT_LD
, .code
=0x46FDUL
, .mask
=0xC7FFUL
, .ops
={UO_2R8_NOM
, UO_MIY
, UO_NONE
}},
604 // instructions w/o operands or with unchangeable operands
605 {.mnemo
=UT_NOP
, .code
=0x00UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
606 {.mnemo
=UT_RLCA
, .code
=0x07UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
607 {.mnemo
=UT_RRCA
, .code
=0x0FUL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
608 {.mnemo
=UT_RLA
, .code
=0x17UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
609 {.mnemo
=UT_RRA
, .code
=0x1FUL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
610 {.mnemo
=UT_DAA
, .code
=0x27UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
611 {.mnemo
=UT_CPL
, .code
=0x2FUL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
612 {.mnemo
=UT_SCF
, .code
=0x37UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
613 {.mnemo
=UT_CCF
, .code
=0x3FUL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
614 {.mnemo
=UT_HALT
, .code
=0x76UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
615 {.mnemo
=UT_RET
, .code
=0xC9UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
616 {.mnemo
=UT_EXX
, .code
=0xD9UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
617 {.mnemo
=UT_DI
, .code
=0xF3UL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
618 {.mnemo
=UT_EI
, .code
=0xFBUL
, .mask
=0xFFUL
, .ops
={UO_NONE
, UO_NONE
, UO_NONE
}},
620 {.mnemo
=UT_LD
, .code
=0xF9UL
, .mask
=0xFFUL
, .ops
={UO_R16SP
, UO_R16HL
, UO_NONE
}},
622 {.mnemo
=UT_EX
, .code
=0x08UL
, .mask
=0xFFUL
, .ops
={UO_R16AF
, UO_R16AFX
, UO_NONE
}},
624 {.mnemo
=UT_EX
, .code
=0x08UL
, .mask
=0xFFUL
, .ops
={UO_R16AFX
, UO_R16AF
, UO_NONE
}},
626 {.mnemo
=UT_EX
, .code
=0xE3UL
, .mask
=0xFFUL
, .ops
={UO_MSP
, UO_R16HL
, UO_NONE
}},
627 // EX HL,(SP) (ditto)
628 {.mnemo
=UT_EX
, .code
=0xE3UL
, .mask
=0xFFUL
, .ops
={UO_R16HL
, UO_MSP
, UO_NONE
}},
630 {.mnemo
=UT_EX
, .code
=0xEBUL
, .mask
=0xFFUL
, .ops
={UO_R16DE
, UO_R16HL
, UO_NONE
}},
632 {.mnemo
=UT_EX
, .code
=0xEBUL
, .mask
=0xFFUL
, .ops
={UO_R16HL
, UO_R16DE
, UO_NONE
}},
634 {.mnemo
=UT_JP
, .code
=0xE9UL
, .mask
=0xFFUL
, .ops
={UO_MHL
, UO_NONE
, UO_NONE
}},
636 {.mnemo
=UT_JP
, .code
=0xE9UL
, .mask
=0xFFUL
, .ops
={UO_R16HL
, UO_NONE
, UO_NONE
}},
638 {.mnemo
=UT_JP
, .code
=0xC3UL
, .mask
=0xFFUL
, .ops
={UO_ADDR16
, UO_NONE
, UO_NONE
}},
640 {.mnemo
=UT_CALL
, .code
=0xCDUL
, .mask
=0xFFUL
, .ops
={UO_ADDR16
, UO_NONE
, UO_NONE
}},
642 {.mnemo
=UT_OUT
, .code
=0xD3UL
, .mask
=0xFFUL
, .ops
={UO_PORTIMM
, UO_R8_A
, UO_NONE
}},
644 {.mnemo
=UT_IN
, .code
=0xDBUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_PORTIMM
, UO_NONE
}},
647 {.mnemo
=UT_ADD
, .code
=0xC6UL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
649 {.mnemo
=UT_ADD
, .code
=0xC6UL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
651 {.mnemo
=UT_ADC
, .code
=0xCEUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
653 {.mnemo
=UT_ADC
, .code
=0xCEUL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
655 {.mnemo
=UT_SUB
, .code
=0xD6UL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
657 {.mnemo
=UT_SUB
, .code
=0xD6UL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
659 {.mnemo
=UT_SBC
, .code
=0xDEUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
661 {.mnemo
=UT_SBC
, .code
=0xDEUL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
663 {.mnemo
=UT_AND
, .code
=0xE6UL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
665 {.mnemo
=UT_AND
, .code
=0xE6UL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
667 {.mnemo
=UT_XOR
, .code
=0xEEUL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
669 {.mnemo
=UT_XOR
, .code
=0xEEUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
671 {.mnemo
=UT_OR
, .code
=0xF6UL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
673 {.mnemo
=UT_OR
, .code
=0xF6UL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
675 {.mnemo
=UT_CP
, .code
=0xFEUL
, .mask
=0xFFUL
, .ops
={UO_IMM8
, UO_NONE
, UO_NONE
}},
677 {.mnemo
=UT_CP
, .code
=0xFEUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_IMM8
, UO_NONE
}},
679 {.mnemo
=UT_LD
, .code
=0x02UL
, .mask
=0xFFUL
, .ops
={UO_MBC
, UO_R8_A
, UO_NONE
}},
681 {.mnemo
=UT_LD
, .code
=0x12UL
, .mask
=0xFFUL
, .ops
={UO_MDE
, UO_R8_A
, UO_NONE
}},
683 {.mnemo
=UT_LD
, .code
=0x0AUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_MBC
, UO_NONE
}},
685 {.mnemo
=UT_LD
, .code
=0x1AUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_MDE
, UO_NONE
}},
687 {.mnemo
=UT_LD
, .code
=0x22UL
, .mask
=0xFFUL
, .ops
={UO_MEM16
, UO_R16HL
, UO_NONE
}},
689 {.mnemo
=UT_LD
, .code
=0x2AUL
, .mask
=0xFFUL
, .ops
={UO_R16HL
, UO_MEM16
, UO_NONE
}},
691 {.mnemo
=UT_LD
, .code
=0x32UL
, .mask
=0xFFUL
, .ops
={UO_MEM16
, UO_R8_A
, UO_NONE
}},
693 {.mnemo
=UT_LD
, .code
=0x3AUL
, .mask
=0xFFUL
, .ops
={UO_R8_A
, UO_MEM16
, UO_NONE
}},
695 {.mnemo
=UT_DJNZ
, .code
=0x10UL
, .mask
=0xFFUL
, .ops
={UO_ADDR8
, UO_NONE
, UO_NONE
}},
697 {.mnemo
=UT_JR
, .code
=0x18UL
, .mask
=0xFFUL
, .ops
={UO_ADDR8
, UO_NONE
, UO_NONE
}},
700 {.mnemo
=UT_ADD
, .code
=0x09UL
, .mask
=0xCFUL
, .ops
={UO_R16HL
, UO_R16
, UO_NONE
}},
703 {.mnemo
=UT_ADD
, .code
=0x80UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
705 {.mnemo
=UT_ADD
, .code
=0x80UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
707 {.mnemo
=UT_ADC
, .code
=0x88UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
709 {.mnemo
=UT_ADC
, .code
=0x88UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
711 {.mnemo
=UT_SUB
, .code
=0x90UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
713 {.mnemo
=UT_SUB
, .code
=0x90UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
715 {.mnemo
=UT_SBC
, .code
=0x98UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
717 {.mnemo
=UT_SBC
, .code
=0x98UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
719 {.mnemo
=UT_AND
, .code
=0xA0UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
721 {.mnemo
=UT_AND
, .code
=0xA0UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
723 {.mnemo
=UT_XOR
, .code
=0xA8UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
725 {.mnemo
=UT_XOR
, .code
=0xA8UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
727 {.mnemo
=UT_OR
, .code
=0xB0UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
729 {.mnemo
=UT_OR
, .code
=0xB0UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
731 {.mnemo
=UT_CP
, .code
=0xB8UL
, .mask
=0xF8UL
, .ops
={UO_R8
, UO_NONE
, UO_NONE
}},
733 {.mnemo
=UT_CP
, .code
=0xB8UL
, .mask
=0xF8UL
, .ops
={UO_R8_A
, UO_R8
, UO_NONE
}},
736 {.mnemo
=UT_JR
, .code
=0x20UL
, .mask
=0xE7UL
, .ops
={UO_JRCOND
, UO_ADDR8
, UO_NONE
}},
739 {.mnemo
=UT_POP
, .code
=0xC1UL
, .mask
=0xCFUL
, .ops
={UO_R16A
, UO_NONE
, UO_NONE
}},
741 {.mnemo
=UT_PUSH
, .code
=0xC5UL
, .mask
=0xCFUL
, .ops
={UO_R16A
, UO_NONE
, UO_NONE
}},
743 {.mnemo
=UT_RET
, .code
=0xC0UL
, .mask
=0xC7UL
, .ops
={UO_COND
, UO_NONE
, UO_NONE
}},
745 {.mnemo
=UT_JP
, .code
=0xC2UL
, .mask
=0xC7UL
, .ops
={UO_COND
, UO_ADDR16
, UO_NONE
}},
747 {.mnemo
=UT_CALL
, .code
=0xC4UL
, .mask
=0xC7UL
, .ops
={UO_COND
, UO_ADDR16
, UO_NONE
}},
749 {.mnemo
=UT_RST
, .code
=0xC7UL
, .mask
=0xC7UL
, .ops
={UO_RSTDEST
, UO_NONE
, UO_NONE
}},
752 {.mnemo
=UT_INC
, .code
=0x04UL
, .mask
=0xC7UL
, .ops
={UO_2R8
, UO_NONE
, UO_NONE
}},
754 {.mnemo
=UT_DEC
, .code
=0x05UL
, .mask
=0xC7UL
, .ops
={UO_2R8
, UO_NONE
, UO_NONE
}},
756 {.mnemo
=UT_LD
, .code
=0x06UL
, .mask
=0xC7UL
, .ops
={UO_2R8
, UO_IMM8
, UO_NONE
}},
759 {.mnemo
=UT_LD
, .code
=0x01UL
, .mask
=0xCFUL
, .ops
={UO_R16
, UO_IMM16
, UO_NONE
}},
761 {.mnemo
=UT_INC
, .code
=0x03UL
, .mask
=0xCFUL
, .ops
={UO_R16
, UO_NONE
, UO_NONE
}},
763 {.mnemo
=UT_DEC
, .code
=0x0BUL
, .mask
=0xCFUL
, .ops
={UO_R16
, UO_NONE
, UO_NONE
}},
766 {.mnemo
=UT_LD
, .code
=0x40UL
, .mask
=0xC0UL
, .ops
={UO_2R8
, UO_R8
, UO_NONE
}},
770 {.mnemo
=UT_LD
, .code
=0x4940UL
, .mask
=0xFFFFUL
, .ops
={UO_R16BC
, UO_R16BC
, UO_NONE
}},
772 {.mnemo
=UT_LD
, .code
=0x4B42UL
, .mask
=0xFFFFUL
, .ops
={UO_R16BC
, UO_R16DE
, UO_NONE
}},
774 {.mnemo
=UT_LD
, .code
=0x4D44UL
, .mask
=0xFFFFUL
, .ops
={UO_R16BC
, UO_R16HL
, UO_NONE
}},
776 {.mnemo
=UT_LD
, .code
=0x5950UL
, .mask
=0xFFFFUL
, .ops
={UO_R16DE
, UO_R16BC
, UO_NONE
}},
778 {.mnemo
=UT_LD
, .code
=0x5B52UL
, .mask
=0xFFFFUL
, .ops
={UO_R16DE
, UO_R16DE
, UO_NONE
}},
780 {.mnemo
=UT_LD
, .code
=0x5D54UL
, .mask
=0xFFFFUL
, .ops
={UO_R16DE
, UO_R16HL
, UO_NONE
}},
782 {.mnemo
=UT_LD
, .code
=0x6960UL
, .mask
=0xFFFFUL
, .ops
={UO_R16HL
, UO_R16BC
, UO_NONE
}},
784 {.mnemo
=UT_LD
, .code
=0x6B62UL
, .mask
=0xFFFFUL
, .ops
={UO_R16HL
, UO_R16DE
, UO_NONE
}},
786 {.mnemo
=UT_LD
, .code
=0x6D64UL
, .mask
=0xFFFFUL
, .ops
={UO_R16HL
, UO_R16HL
, UO_NONE
}},
790 // instructions unaffected by DD/FF prefixes
791 // this table used by disassembler (we don't want to eat prefixes)
792 const unsigned char URASM_DDFD_INSENSITIVE
[256] = {
793 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
794 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
795 1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,
796 1,1,1,1,0,0,0,1,1,0,1,1,1,1,1,1,
797 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
798 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
799 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
800 0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,1,
801 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
802 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
803 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
804 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
805 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
806 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
807 1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,
808 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
810 0xff,0xbf,0xff,0xbf,0x81,0x81,0xf1,0xbf,0xf1,0xf1,0xf1,0xf1,0x00,0x00,0x02,0xf1,
811 0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xff,0xef,0xff,0xff,0xab,0xbf,0xff,0xbf,
815 #define isDDSensitive(c) URASM_DDFD_INSENSITIVE[(c)&0xff]
817 static inline int isDDSensitive (uint8_t opc) {
818 return URASM_DDFD_INSENSITIVE[opc/8]&(0x80>>(opc%8));
824 const unsigned char URASM_DDFD_HAS_DISP
[256] = {
826 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
827 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
828 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
829 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,
830 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
831 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
832 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
833 1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,
834 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
835 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
836 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
837 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,
838 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
839 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
841 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
843 0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0xfd,0x02,
844 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
847 static inline int hasDDFDDisp (uint8_t opc
) {
848 return URASM_DDFD_HAS_DISP
[opc
/8]&(0x80>>(opc
%8));
853 static const char *findLabelByAddr (uint16_t addr
) {
854 if (!urFindLabelByAddr
) return NULL
;
855 return urFindLabelByAddr(addr
);
859 ///////////////////////////////////////////////////////////////////////////////
863 // nextW: next 2 bytes (after opcode)
864 // idx: I? displacement
865 static void uaOp2Str (char *res
, int op
, uint16_t addr
, uint8_t opc
, uint16_t nextW
, int idx
) {
870 case UO_NONE
: strcpy(res
, ""); break;
872 if (!urDisDecimal
) sprintf(res
, "#%02X", nextW
&0xFFU
); else sprintf(res
, "%u", nextW
&0xFFU
);
875 if (!urDisDecimal
) sprintf(res
, "#%04X", nextW
); else sprintf(res
, "%u", nextW
);
878 addr
+= 2; nextW
&= 0xFFU
;
879 add
= nextW
<128 ? nextW
: ((int)nextW
)-256;
885 lbl
= findLabelByAddr(nextW
);
886 if (lbl
) { strcpy(res
, lbl
); break; }
887 lbl
= findLabelByAddr(nextW
-1);
888 if (lbl
) { sprintf(res
, "%s-1", lbl
); break; }
889 lbl
= findLabelByAddr(nextW
-2);
890 if (lbl
) { sprintf(res
, "%s-2", lbl
); break; }
891 lbl
= findLabelByAddr(nextW
+1);
892 if (lbl
) { sprintf(res
, "%s+1", lbl
); break; }
893 lbl
= findLabelByAddr(nextW
+2);
894 if (lbl
) { sprintf(res
, "%s+2", lbl
); break; }
895 if (!urDisDecimal
) sprintf(res
, "#%04X", nextW
); else sprintf(res
, "%u", nextW
);
899 strcpy(res
, "("); ++res
;
903 strcpy(res
, URA_REGS8
[opc
&0x07UL
]);
907 strcpy(res
, URA_REGS8
[(opc
>>3)&0x07UL
]);
909 case UO_PORTC
: strcpy(res
, "(C)"); break;
911 if (!urDisDecimal
) sprintf(res
, "(#%02X)", nextW
&0xFFU
); else sprintf(res
, "(%u)", nextW
&0xFFU
);
913 case UO_R8_XH
: strcpy(res
, "XH"); break;
914 case UO_R8_XL
: strcpy(res
, "XL"); break;
915 case UO_R8_YH
: strcpy(res
, "YH"); break;
916 case UO_R8_YL
: strcpy(res
, "YL"); break;
917 case UO_R8_A
: strcpy(res
, "A"); break;
918 case UO_R8_R
: strcpy(res
, "R"); break;
919 case UO_R8_I
: strcpy(res
, "I"); break;
920 case UO_R16
: strcpy(res
, URA_REGS16
[(opc
>>4)&0x03UL
]); break;
921 case UO_R16A
: strcpy(res
, URA_REGS16A
[(opc
>>4)&0x03UL
]); break;
922 case UO_R16AF
: strcpy(res
, "AF"); break;
923 case UO_R16AFX
: strcpy(res
, "AF'"); break;
924 case UO_R16BC
: strcpy(res
, "BC"); break;
925 case UO_R16DE
: strcpy(res
, "DE"); break;
926 case UO_R16HL
: strcpy(res
, "HL"); break;
927 case UO_R16IX
: strcpy(res
, "IX"); break;
928 case UO_R16IY
: strcpy(res
, "IY"); break;
929 case UO_R16SP
: strcpy(res
, "SP"); break;
930 case UO_MSP
: strcpy(res
, "(SP)"); break;
931 case UO_MBC
: strcpy(res
, "(BC)"); break;
932 case UO_MDE
: strcpy(res
, "(DE)"); break;
933 case UO_MHL
: strcpy(res
, "(HL)"); break;
934 case UO_MIX0
: strcpy(res
, "(IX)"); break;
935 case UO_MIY0
: strcpy(res
, "(IY)"); break;
937 sprintf(res
, "(IX%c%d)", idx
<0?'-':'+', idx
);
940 sprintf(res
, "(IY%c%d)", idx
<0?'-':'+', idx
);
942 case UO_JRCOND
: strcpy(res
, URA_COND
[(opc
>>3)&0x03U
]); break;
943 case UO_COND
: strcpy(res
, URA_COND
[(opc
>>3)&0x07U
]); break;
944 case UO_BITN
: sprintf(res
, "%u", (opc
>>3)&0x07U
); break;
946 if (!urDisDecimal
) sprintf(res
, "#%02X", opc
&0x38U
); else sprintf(res
, "%u", opc
&0x38U
);
948 case UO_IM0
: strcpy(res
, "0"); break;
949 case UO_IM1
: strcpy(res
, "1"); break;
950 case UO_IM2
: strcpy(res
, "2"); break;
951 default: strcpy(res
, ""); break; // we'll never come here
953 if (ismem
) strcat(res
, ")");
957 // find the corresponding record in URASM_COMMANDS
958 int urDisassembleFind (uint16_t addr
) {
964 if (!urGetByte
) return -1;
965 for (f
= 0; f
< 8; ++f
) buf
[f
] = urGetByte(addr
+f
);
966 if (buf
[0] == 0xDDU
|| buf
[0] == 0xFDU
) {
968 if (isDDSensitive(buf
[1])) return buf
[0]==0xDDU
? 0 : 1;
970 ci
= ((uint32_t)buf
[0]) | (((uint32_t)buf
[1])<<8) | (((uint32_t)buf
[2])<<16) | (((uint32_t)buf
[3])<<24);
971 for (opn
= 0; opn
<= URASM_MAX_COMMAND
; ++opn
) {
973 for (; opn
<= URASM_MAX_COMMAND
&& (ci
&URASM_COMMANDS
[opn
].mask
) != URASM_COMMANDS
[opn
].code
; ++opn
) ;
974 if (opn
> URASM_MAX_COMMAND
) {
975 if (buf
[0] == 0xEDU
) return -2;
978 // skip prefixes, determine command length
979 f
= URASM_COMMANDS
[opn
].mask
; c
= URASM_COMMANDS
[opn
].code
;
980 for (bpos
= 0; ; ++bpos
) {
982 if ((f
&0xFFUL
) != 0xFFUL
) break;
984 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
987 // are there any operands?
988 if (URASM_COMMANDS
[opn
].ops
[0] == UO_NONE
) return opn
;
989 // is this CB-prefixed?
990 if (((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBDDUL
) ||
991 ((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
)) ++bpos
; // skip displacement
994 for (f
= 0; f
<= 3; ++f
) {
995 if (f
== 3) return opn
;
996 op
= URASM_COMMANDS
[opn
].ops
[f
];
997 if (op
== UO_NONE
) return opn
;
998 // check for valid operand
999 if (op
== UO_R8_NOM
) {
1000 if ((opc
&0x07U
) == 6) break; // bad (HL)
1002 if (op
== UO_2R8_NOM
) {
1003 if (((opc
>>3)&0x07U
) == 6) break; // bad (HL)
1011 // length of the corresponding instruction
1012 int urDisassembleLength (int idx
) {
1016 if (idx
== -2) return 2;
1017 if (idx
< 0 || idx
> URASM_MAX_COMMAND
) return 1;
1018 if (idx
< 2) return 1;
1019 m
= URASM_COMMANDS
[idx
].mask
; c
= URASM_COMMANDS
[idx
].code
;
1022 if (((m&0xFFFFUL) == 0xFFFFUL) &&
1023 ((c&0xFF00UL) == 0xCBUL) && ((c&0xFFUL) == 0xDDUL || (c&0xFFUL) == 0xFDUL)) return 4;
1025 // skip prefixes, determine command length
1028 if ((m
&0xFFUL
) != 0xFFUL
) break;
1030 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
1031 m
>>= 8; c
>>= 8; ++res
;
1033 // is this CB-prefixed?
1034 if (((URASM_COMMANDS
[idx
].code
&0xFFFFUL
) == 0xCBDDUL
) ||
1035 ((URASM_COMMANDS
[idx
].code
&0xFFFFUL
) == 0xCBFDUL
)) m
>>= 8;
1037 while (m
!= 0) { m
>>= 8; ++res
; }
1039 for (f
= 0; f
<= 2; ++f
) {
1040 op
= URASM_COMMANDS
[idx
].ops
[f
];
1041 if (op
== UO_NONE
) break;
1043 // command with displacement
1044 case UO_MIX
: case UO_MIY
: ++res
; break;
1045 // command has immediate operand
1046 case UO_IMM8
: case UO_ADDR8
: case UO_PORTIMM
: ++res
; break;
1047 case UO_IMM16
: case UO_ADDR16
: case UO_MEM16
: res
+= 2; break;
1054 int urDisassembleOne (char *dstr
, uint16_t addr
) {
1063 if (!urGetByte
) return -1;
1064 for (f
= 0; f
< 8; ++f
) buf
[f
] = urGetByte(addr
+f
);
1065 if (buf
[0] == 0xDDU
|| buf
[0] == 0xFDU
) {
1067 if (isDDSensitive(buf
[1])) {
1068 strcpy(dstr
, URASM_TOKENS
[buf
[0]==0xDDU
? UT_NOPX
: UT_NOPY
]);
1071 // take possible I? displacement
1072 idx
= (int8_t)buf
[2];
1074 ci
= ((uint32_t)buf
[0]) | (((uint32_t)buf
[1])<<8) | (((uint32_t)buf
[2])<<16) | (((uint32_t)buf
[3])<<24);
1076 for (opn
= 0; opn
<= URASM_MAX_COMMAND
; ++opn
) {
1077 res
= 0; dstr
[0] = '\0';
1079 for (; opn
<= URASM_MAX_COMMAND
&& (ci
&URASM_COMMANDS
[opn
].mask
) != URASM_COMMANDS
[opn
].code
; ++opn
) ;
1080 if (opn
> URASM_MAX_COMMAND
) {
1081 if (buf
[0] == 0xEDU
) {
1082 if (!urDisDecimal
) sprintf(opstr
, "#%02X,#%02X", buf
[0], buf
[1]); else sprintf(opstr
, "%u,%u", buf
[0], buf
[1]);
1083 /*if (!urDisDecimal) sprintf(opstr, "#%04X", (uint16_t)buf[0]|(((uint16_t)buf[1])<<8));
1084 else sprintf(opstr, "%u", (uint16_t)buf[0]|(((uint16_t)buf[1])<<8));*/
1085 sprintf(dstr
, "DB\t%s", opstr
);
1088 if (!urDisDecimal
) sprintf(opstr
, "#%02X", buf
[0]); else sprintf(opstr
, "%u", buf
[0]);
1089 sprintf(dstr
, "DB\t%s", opstr
);
1092 // skip prefixes, determine command length
1093 f
= URASM_COMMANDS
[opn
].mask
; c
= URASM_COMMANDS
[opn
].code
;
1094 for (bpos
= 0; ; ++bpos
) {
1096 if ((f
&0xFFUL
) != 0xFFUL
) break;
1098 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
1099 f
>>= 8; c
>>= 8; ++res
;
1101 // is this CB-prefixed?
1102 if (((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBDDUL
) ||
1103 ((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
)) f
>>= 8;
1104 while (f
!= 0) { f
>>= 8; ++res
; }
1106 strcpy(dstr
, URASM_TOKENS
[URASM_COMMANDS
[opn
].mnemo
]);
1107 // are there any operands?
1108 if (URASM_COMMANDS
[opn
].ops
[0] == UO_NONE
) return res
;
1109 // is this CB-prefixed?
1110 if (((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBDDUL
) ||
1111 ((URASM_COMMANDS
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
)) ++bpos
; // skip displacement
1113 if ((URASM_COMMANDS
[opn
].ops
[0] == UO_MIX
|| URASM_COMMANDS
[opn
].ops
[0] == UO_MIY
) &&
1114 URASM_COMMANDS
[opn
].ops
[1] == UO_IMM8
&&
1115 URASM_COMMANDS
[opn
].ops
[2] == UO_NONE
) ++bpos
; // skip displacement
1118 nextW
= (uint16_t)buf
[bpos
] | (((uint16_t)buf
[bpos
+1])<<8);
1120 for (f
= 0; f
<= 3; ++f
) {
1122 //printf("OPN=%d\n", opn);
1125 op
= URASM_COMMANDS
[opn
].ops
[f
];
1126 if (op
== UO_NONE
) {
1127 //printf("OPN=%d\n", opn);
1130 // check for valid operand
1131 if (op
== UO_R8_NOM
) {
1132 if ((opc
&0x07U
) == 6) break; // bad (HL)
1134 if (op
== UO_2R8_NOM
) {
1135 if (((opc
>>3)&0x07U
) == 6) break; // bad (HL)
1137 // command with displacement?
1138 if (op
== UO_MIX
|| op
== UO_MIY
) ++res
;
1139 // command has immediate operand?
1140 if (op
== UO_IMM8
|| op
== UO_ADDR8
|| op
== UO_PORTIMM
) ++res
;
1141 if (op
== UO_IMM16
|| op
== UO_ADDR16
|| op
== UO_MEM16
) res
+= 2;
1143 strcat(dstr
, f
==0?"\t":",");
1145 uaOp2Str(opstr
, op
, addr
, opc
, nextW
, idx
);
1146 strcat(dstr
, opstr
);
1153 ///////////////////////////////////////////////////////////////////////////////
1156 // returns false if label name conflicts with reserved word
1157 // (or if label is just invalid one)
1158 int urIsValidLabelName (const char *lbl
) {
1162 if (!lbl
|| !lbl
[0]) return 0;
1163 if (lbl
[0] == '@') {
1168 if (isdigit(ch
)) return 0;
1169 if (!isalpha(ch
) && ch
!= '.' && ch
!= '_' && ch
!= '@') return 0;
1170 for (f
= 1; lbl
[f
]; ++f
) {
1172 if (isdigit(ch
)) continue;
1175 if (ch
!= '$' && ch
!= '.' && ch
!= '_' && ch
!= '@') return 0;
1178 if (hasNA
|| f
> 4) return 1;
1179 for (f
= 0; lbl
[f
]; ++f
) buf
[f
] = toupper(lbl
[f
]); buf
[f
] = '\0';
1180 for (f
= 0; f
< URASM_MAX_TOKEN
; ++f
) if (!strcmp(buf
, URASM_TOKENS
[f
])) return 0;
1181 for (f
= 0; f
< 8; ++f
) if (!strcmp(buf
, URA_REGS8
[f
])) return 0;
1182 for (f
= 0; f
< 4; ++f
) if (!strcmp(buf
, URA_REGS16
[f
])) return 0;
1183 for (f
= 0; f
< 4; ++f
) if (!strcmp(buf
, URA_REGS16A
[f
])) return 0;
1184 for (f
= 0; f
< 8; ++f
) if (!strcmp(buf
, URA_COND
[f
])) return 0;
1185 if (!strcmp(buf
, "AFX")) return 0;
1186 if (!strcmp(buf
, "IXH")) return 0;
1187 if (!strcmp(buf
, "IXL")) return 0;
1188 if (!strcmp(buf
, "IYH")) return 0;
1189 if (!strcmp(buf
, "IYL")) return 0;
1190 if (!strcmp(buf
, "IX")) return 0;
1191 if (!strcmp(buf
, "IY")) return 0;
1192 if (!strcmp(buf
, "XH")) return 0;
1193 if (!strcmp(buf
, "HX")) return 0;
1194 if (!strcmp(buf
, "XL")) return 0;
1195 if (!strcmp(buf
, "LX")) return 0;
1196 if (!strcmp(buf
, "YH")) return 0;
1197 if (!strcmp(buf
, "HY")) return 0;
1198 if (!strcmp(buf
, "YL")) return 0;
1199 if (!strcmp(buf
, "LY")) return 0;
1200 if (!strcmp(buf
, "R")) return 0;
1201 if (!strcmp(buf
, "I")) return 0;
1206 ///////////////////////////////////////////////////////////////////////////////
1209 // parse and calculate expression
1210 static const char *skipBlanks (const char *expr
) {
1211 while (*expr
&& isspace(*expr
)) ++expr
;
1216 static inline int dig2n (char ch
, int base
) {
1217 if (ch
< '0') return -1;
1219 if (ch
> '0'+base
) return -1;
1223 if (ch
> '9' && ch
< 'A') return -1;
1224 ch
-= '0'+(ch
>'9'?7:0);
1225 if (ch
>= base
) return -1;
1230 ///////////////////////////////////////////////////////////////////////////////
1231 // expression parser
1233 const char *expr
; /* can be changed */
1234 uint16_t addr
; /* current address */
1235 int defined
; /* !0: all used labels are defined */
1236 int error
; /* !0: error */
1237 const char *errpos
; /* will be set on error, has no meaning otherwise */
1244 int32_t val
; /* for now */
1248 /* do math; op0 is the result */
1249 typedef void (*ExprDoItFn
) (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
);
1252 char sn
; /* short name or 0 */
1253 const char *ln
; /* long name or NULL if `sn`!=0 */
1254 int prio
; /* priority */
1259 ///////////////////////////////////////////////////////////////////////////////
1263 #define ERR_PARENS 3
1264 #define ERR_NUMBER 4
1265 #define ERR_STRING 5
1270 #define EERROR(code) longjmp(ei->errJP, code)
1272 static void mdoBitNot (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= ~op0
->val
; }
1273 static void mdoLogNot (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= !op0
->val
; }
1274 static void mdoBitAnd (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
&= op1
->val
; }
1275 static void mdoBitOr (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
|= op1
->val
; }
1276 static void mdoBitXor (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
^= op1
->val
; }
1277 static void mdoLShift (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
<<= op1
->val
; }
1278 static void mdoRShift (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
>>= op1
->val
; }
1279 static void mdoMul (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
*= op1
->val
; }
1280 static void mdoDiv (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { if (op1
->val
== 0) EERROR(ERR_DIV0
); op0
->val
/= op1
->val
; }
1281 static void mdoMod (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { if (op1
->val
== 0) EERROR(ERR_DIV0
); op0
->val
%= op1
->val
; }
1282 static void mdoAdd (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
+= op1
->val
; }
1283 static void mdoSub (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
-= op1
->val
; }
1284 static void mdoLogLess (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
< op1
->val
; }
1285 static void mdoLogGreat (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
> op1
->val
; }
1286 static void mdoLogEqu (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
== op1
->val
; }
1287 static void mdoLogNEqu (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
!= op1
->val
; }
1288 static void mdoLogLEqu (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
>= op1
->val
; }
1289 static void mdoLogGEqu (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) { op0
->val
= op0
->val
>= op1
->val
; }
1291 static void mdoLogAnd (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) {
1292 ei
->logRes
= op0
->val
= (op0
->val
&& op1
->val
);
1293 if (!op0
->val
) ei
->logDone
= 1;
1296 static void mdoLogOr (ExprOp
*op0
, ExprOp
*op1
, ExprInfo
*ei
) {
1297 ei
->logRes
= op0
->val
= (op0
->val
|| op1
->val
);
1298 if (op0
->val
) ei
->logDone
= 1;
1302 // priority level 1 -- opertiors line "." and "[]", function calls
1303 // priority level 2 -- unary opertiors like "!" and "~"
1304 // priority level 7 -- always right-associative! (PRIO_RIGHT)
1305 // short forms must be put before long
1306 // priorities must be sorted
1307 static const ExprOperator operators
[] = {
1308 { '~', NULL
, 2, mdoBitNot
},
1309 { '!', NULL
, 2, mdoLogNot
},
1311 { 0, "<<", 3, mdoLShift
},
1312 { 0, ">>", 3, mdoRShift
},
1314 { '&', NULL
, 4, mdoBitAnd
},
1316 { '|', NULL
, 5, mdoBitOr
},
1317 { '^', NULL
, 5, mdoBitXor
},
1319 { '*', NULL
, 6, mdoMul
},
1320 { '/', NULL
, 6, mdoDiv
},
1321 { '%', NULL
, 6, mdoMod
},
1323 { '+', NULL
, 7, mdoAdd
},
1324 { '-', NULL
, 7, mdoSub
},
1326 { 0, "&&", 8, mdoLogAnd
},
1328 { 0, "||", 9, mdoLogOr
},
1330 { '<', NULL
, 10, mdoLogLess
},
1331 { '>', NULL
, 10, mdoLogGreat
},
1332 { '=', NULL
, 10, mdoLogEqu
},
1333 { 0, "==", 10, mdoLogEqu
},
1334 { 0, "!=", 10, mdoLogNEqu
},
1335 { 0, "<>", 10, mdoLogNEqu
},
1336 { 0, "<=", 10, mdoLogLEqu
},
1337 { 0, ">=", 10, mdoLogGEqu
},
1338 { 0, NULL
, -1, NULL
},
1341 #define UNARY_PRIO 2
1344 ///////////////////////////////////////////////////////////////////////////////
1345 // expression parser engine
1346 static void expression (ExprOp
*res
, ExprInfo
*ei
);
1347 //int *res, const char *expr, uint16_t addr, int *defined, int *error);
1350 #define SKIP_BLANKS { ei->errpos = ei->expr = skipBlanks(ei->expr); }
1352 static const char *parseNumber (ExprOp
*res
, const char *expr
, int *error
) {
1353 int noH
= 1, n
= 0, base
;
1356 if (*error
) return expr
;
1357 if (!expr
[0]) { *error
= 1; return expr
; }
1358 /* can it be hex? */
1359 for (p
= expr
; *p
&& isxdigit(*p
); ++p
) ;
1360 if (toupper(*p
) == 'H') {
1366 if (toupper(expr
[1]) == 'X') {
1373 case '%': base
= 2; ++expr
; break;
1374 //case '@': base = 8; ++expr; break;
1375 case '#': case '$': base
= 16; ++expr
; break;
1376 case '1' ... '9': base
= 10; break;
1377 default: *error
= 1; return expr
;
1380 if (dig2n(*expr
, base
) < 0) { *error
= 1; return expr
-(base
!=10?1:0); }
1384 if (*expr
== '_') { ++expr
; continue; }
1385 if ((d
= dig2n(*expr
++, base
)) < 0) { res
->val
= n
; return expr
-noH
; }
1392 static void getAddr (const char *lbl
, ExprOp
*res
, ExprInfo
*ei
) {
1393 int defined
= 0, found
= 0;
1396 if (!urFindLabelByName
) EERROR(ERR_LABEL
);
1397 val
= urFindLabelByName(lbl
, ei
->addr
, &defined
, &found
);
1398 if (!found
) EERROR(ERR_LABEL
);
1399 if (!defined
) ei
->defined
= 0;
1404 // !0: invalid label
1405 static int readLabelName (char *buf
, ExprInfo
*ei
) {
1408 if (pos
>= 128) return -3;
1409 char ch
= ei
->expr
[0];
1411 if (isalnum(ch
) || ch
== '$' || ch
== '.' || ch
== '_' || ch
== '@') {
1412 buf
[pos
++] = ch
; ++(ei
->expr
);
1417 if (pos
< 1) return -2;
1419 if (!urIsValidLabelName(buf
)) return -1;
1424 static void fnDefKn (ExprOp
*res
, ExprInfo
*ei
, int qtype
) {
1426 if (readLabelName(lbl
, ei
)) EERROR(ERR_LABEL
);
1428 if (ei
->expr
[0] != ')') EERROR(ERR_FUNC
);
1430 if (ei
->logDone
) return;
1431 res
->val
= urIsLabelDefinedOrKnown
? (urIsLabelDefinedOrKnown(lbl
, ei
->addr
, qtype
) != 0) : 0;
1434 static void fnDefined (ExprOp
*res
, ExprInfo
*ei
) { fnDefKn(res
, ei
, UR_QTYPE_DEFINED
); }
1435 static void fnKnown (ExprOp
*res
, ExprInfo
*ei
) { fnDefKn(res
, ei
, UR_QTYPE_KNOWN
); }
1438 static void fnAligned256 (ExprOp
*res
, ExprInfo
*ei
) {
1442 if (ei
->expr
[0] != ')') EERROR(ERR_FUNC
);
1444 if (ei
->logDone
) return;
1445 res
->val
= v
.val
%256?0:1;
1449 static void fnSameSeg (ExprOp
*res
, ExprInfo
*ei
) {
1452 expression(&v0
, ei
);
1453 if (ei
->expr
[0] != ',') EERROR(ERR_FUNC
);
1455 expression(&v1
, ei
);
1456 if (ei
->expr
[0] != ')') EERROR(ERR_FUNC
);
1458 if (ei
->logDone
) return;
1459 res
->val
= v0
.val
/256==v1
.val
/256;
1463 static void fnAlign (ExprOp
*res
, ExprInfo
*ei
) {
1466 expression(&v0
, ei
);
1467 if (ei
->expr
[0] == ',') {
1469 expression(&v1
, ei
);
1473 if (ei
->expr
[0] != ')') EERROR(ERR_FUNC
);
1474 if (v1
.val
< 1) EERROR(ERR_FUNC
);
1476 if (ei
->logDone
) return;
1477 res
->val
= (v0
.val
+v1
.val
-1)/v1
.val
*v1
.val
;
1481 static void term (ExprOp
*res
, ExprInfo
*ei
) {
1483 int tmp
= 0, f
, c
, base
;
1485 int xDigit (char ch
, int base
) {
1486 if (ch
< '0') return -1;
1488 if (ch
>= '0'+base
) return -1;
1492 if (ch
<= '9') return ch
-'0';
1493 if (ch
< 'A' || ch
> 'A'+base
-10) return -1;
1495 return ch
<base
? ch
: -1;
1499 ch
= (ei
->errpos
= ei
->expr
)[0];
1500 if (!ch
) EERROR(ERR_EOS
);
1504 ch
= ch
=='[' ? ']' : ')';
1505 expression(res
, ei
);
1506 if (ei
->expr
[0] != ch
) EERROR(ERR_PARENS
);
1509 case '0' ... '9': case '#': case '%':
1511 ei
->expr
= parseNumber(res
, ei
->expr
, &tmp
);
1512 if (tmp
) EERROR(ERR_NUMBER
);
1515 if (dig2n(ei
->expr
[1], 16) >= 0) goto donumber
;
1516 res
->val
= ei
->addr
;
1519 case '"': // char or 2 chars
1520 case '\'': // char or 2 reversed chars
1523 // max 2 chars allowed here
1524 for (c
= 0; c
< 2; ++c
) {
1525 char cc
= *ei
->expr
;
1526 if (cc
== ch
) break; // done
1529 switch (*(++ei
->expr
)) {
1530 case '\0': EERROR(ERR_EOS
);
1531 case 'a': cc
= '\a'; break;
1532 case 'b': cc
= '\b'; break;
1533 case 'f': cc
= '\f'; break;
1534 case 'n': cc
= '\n'; break;
1535 case 'r': cc
= '\r'; break;
1536 case 't': cc
= '\t'; break;
1537 case 'v': cc
= '\v'; break;
1538 case 'z': cc
= '\0'; break;
1539 case 'x': case 'X': // hex
1540 base
= 16; f
= 2; ++ei
->expr
;
1541 donum
: for (cc
= 0; f
> 0; --f
) {
1542 char c1
= xDigit(*(ei
->expr
++), base
);
1543 if (c1
< 0) { --(ei
->expr
); break; }
1547 if (cc
> 255) EERROR(ERR_STRING
);
1548 --(ei
->expr
); // return to the last digit, 'for' will skip it
1553 case '1' ... '9': // decimal
1556 default: cc
= *(ei
->expr
); break; // others
1559 if (c
== 0) res
->val
= cc
&0xFFU
;
1561 if (ch
== '"') res
->val
|= (cc
&0xFFU
)<<(8*c
);
1562 else res
->val
= (res
->val
<<8)|(cc
&0xFFU
);
1565 if (*ei
->expr
!= ch
) EERROR(ERR_STRING
);
1575 if (readLabelName(lbl
, ei
)) EERROR(ERR_LABEL
);
1577 if (ei
->expr
[0] == '(') {
1580 if (strcmp(lbl
, "defined") == 0) fnDefined(res
, ei
);
1581 else if (strcmp(lbl
, "known") == 0) fnKnown(res
, ei
);
1582 else if (strcmp(lbl
, "aligned256") == 0) fnAligned256(res
, ei
);
1583 else if (strcmp(lbl
, "sameseg") == 0) fnSameSeg(res
, ei
);
1584 else if (strcmp(lbl
, "align") == 0) fnAlign(res
, ei
);
1585 else EERROR(ERR_FUNC
);
1588 if (!ei
->logDone
) getAddr(lbl
, res
, ei
);
1595 static const ExprOperator
*getOperator (int prio
, ExprInfo
*ei
) {
1596 char opc
= ei
->expr
[0];
1598 const ExprOperator
*res
= operators
, *cur
;
1600 //for (; res->prio > 0; ++res) if (res->prio == prio) break;
1601 //if (res->prio < 0) return NULL;
1602 //for (cur = res, res = NULL; cur->prio == prio; ++cur) {
1603 for (cur
= res
, res
= NULL
; cur
->prio
>= 0; ++cur
) {
1605 if (oplen
> 1) continue;
1606 if (opc
== cur
->sn
) res
= cur
;
1608 int l
= strlen(cur
->ln
);
1609 if (l
< oplen
) continue;
1610 if (!strncmp(ei
->expr
, cur
->ln
, l
)) { res
= cur
; oplen
= l
; }
1613 if (res
&& res
->prio
!= prio
) res
= NULL
;
1614 //if (res) printf("res: '%c' \"%s\"\n", res->sn, res->ln);
1615 if (res
) ei
->expr
+= oplen
; /* eat operator */
1620 static void expressionDo (int prio
, ExprOp
*res
, ExprInfo
*ei
) {
1621 const ExprOperator
*op
;
1625 if (ei
->expr
[0] == ')' || ei
->expr
[0] == ']') return;
1626 if (prio
<= 0) { term(res
, ei
); return; }
1627 if (prio
== UNARY_PRIO
) {
1631 ei
->errpos
= ei
->expr
;
1632 if (!(op
= getOperator(prio
, ei
))) break;
1633 //expression(res, ei);
1634 expressionDo(prio
, res
, ei
);
1635 if (!ei
->logDone
) op
->doer(res
, &o1
, ei
); else res
->val
= ei
->logRes
;
1638 if (!wasIt
) expressionDo(prio
-1, res
, ei
);
1641 expressionDo(prio
-1, res
, ei
); // first operand
1644 ei
->errpos
= ei
->expr
;
1645 if (!ei
->expr
[0] || ei
->expr
[0] == ';' || ei
->expr
[0] == ':' || ei
->expr
[0] == ')' || ei
->expr
[0] == ']') break;
1646 if (!(op
= getOperator(prio
, ei
))) break;
1650 if (!res
->val
) { ei
->logDone
= 1; ei
->logRes
= 0; }
1653 if (res
->val
) { ei
->logDone
= 1; ei
->logRes
= res
->val
; }
1657 expressionDo(prio
-1, &o1
, ei
); // second operand
1658 if (!ei
->logDone
) op
->doer(res
, &o1
, ei
); else res
->val
= ei
->logRes
;
1663 static void expression (ExprOp
*res
, ExprInfo
*ei
) {
1666 ei
->errpos
= ei
->expr
;
1667 switch (ei
->expr
[0]) {
1668 case '\0': EERROR(ERR_EOS
);
1669 case '-': neg
= 1; ++(ei
->expr
); break;
1670 case '+': neg
= 0; ++(ei
->expr
); break;
1673 expressionDo(MAX_PRIO
, res
, ei
);
1674 if (neg
) res
->val
= -(res
->val
);
1679 const char *urExpression (int32_t *res
, const char *expr
, uint16_t addr
, int *defined
, int *error
) {
1684 if (error
) *error
= 0;
1685 if (defined
) *defined
= 1;
1686 if (!expr
) { if (error
) *error
= ERR_EOS
; return NULL
; }
1694 jr
= setjmp(ei
.errJP
);
1696 if (error
) *error
= ei
.error
;
1699 expression(&r
, &ei
);
1700 if (res
) *res
= r
.val
;
1701 if (defined
) *defined
= ei
.defined
;
1706 ///////////////////////////////////////////////////////////////////////////////
1709 const char *urNextOperand (URAOperand
*op
, const char *expr
, uint16_t addr
, int *error
) {
1711 char opstr
[256], inQ
= 0;
1715 memset(op
, 0, sizeof(URAOperand
));
1717 expr
= skipBlanks(expr
);
1718 if (!expr
[0] || expr
[0] == ';') return NULL
;
1719 if (expr
[0] == ':') return expr
;
1721 // get operand string
1722 for (oe
= expr
; *expr
; ++expr
) {
1725 if (ch
== inQ
) inQ
= 0;
1727 if (ch
== '"' || ch
== '`') inQ
= ch
;
1728 else if (ch
== '\'' && (oe
== expr
|| !isalnum(expr
[-1]))) inQ
= ch
;
1729 else if (ch
== '\\' && expr
[1]) ++expr
;
1730 else if (!inQ
&& ch
== ',') break;
1731 else if (ch
== ';' || ch
== ':') break;
1734 if (expr
-oe
> 255) { *error
= 1; return oe
; }
1735 memset(opstr
, 0, sizeof(opstr
));
1736 memcpy(opstr
, oe
, expr
-oe
);
1737 while (opstr
[0] && isspace(opstr
[strlen(opstr
)-1])) opstr
[strlen(opstr
)-1] = '\0';
1738 if (!opstr
[0]) { *error
= 1; return oe
; }
1739 // determine operand type
1740 if (isalpha(opstr
[0]) && urIsValidLabelName(opstr
)) {
1744 if (opstr
[0] == '(') {
1746 op
->mem
= 1; op
->special
= 1;
1747 if (!opstr
[1] || opstr
[strlen(opstr
)-1] != ')') { *error
= 1; return oe
; }
1749 opstr
[strlen(opstr
)-1] = '\0';
1750 memmove(opstr
, opstr
+1, sizeof(opstr
)-1);
1752 while (opstr
[0] && isspace(opstr
[0])) memmove(opstr
, opstr
+1, sizeof(opstr
)-1);
1753 while (opstr
[0] && isspace(opstr
[strlen(opstr
)-1])) opstr
[strlen(opstr
)-1] = '\0';
1755 if (!opstr
[0]) { *error
= 1; return oe
; }
1756 for (f
= 0; opstr
[f
]; ++f
) op
->s
[f
] = toupper(opstr
[f
]);
1757 if (!strcmp(op
->s
, "C")) {
1758 op
->special
= 1; op
->mem
= 0; strcpy(op
->s
, "(C)");
1761 if (!strcmp(op
->s
, "HL")) return expr
;
1762 if (!strcmp(op
->s
, "DE")) return expr
;
1763 if (!strcmp(op
->s
, "BC")) return expr
;
1764 if (!strcmp(op
->s
, "SP")) return expr
;
1765 if (op
->s
[0] == 'I' && (op
->s
[1] == 'X' || op
->s
[1] == 'Y')) {
1767 op
->ixy
= op
->s
[1]=='X' ? 0xDDU
: 0xFDU
;
1769 memmove(opstr
, opstr
+1, sizeof(opstr
)-1);
1771 while (opstr
[1] && isspace(opstr
[1])) memmove(opstr
+1, opstr
+2, sizeof(opstr
)-2);
1772 if (!opstr
[1]) return expr
;
1773 if (opstr
[1] != '+' && opstr
[1] != '-') { *error
= 1; return oe
; }
1774 // opstr must be an expression
1775 const char *t
= urExpression(&op
->v
, opstr
, addr
, &op
->defined
, error
);
1776 if (*error
) return oe
;
1777 if (t
[0]) { *error
= 1; return oe
; }
1778 if (op
->defined
&& (op
->v
< -128 || op
->v
> 127)) { *error
= 1; return oe
; }
1783 if (!strcasecmp(opstr
, "af'")) goto registerop
;
1784 for (f
= 0; isalpha(opstr
[f
]); ++f
) ;
1787 for (f
= 0; opstr
[f
]; ++f
) opstr
[f
] = toupper(opstr
[f
]);
1788 strcpy(op
->s
, opstr
);
1790 return skipBlanks(expr
);
1793 // this must be an expression
1795 strcpy(op
->s
, opstr
);
1796 const char *t
= urExpression(&op
->v
, opstr
, addr
, &op
->defined
, error
);
1797 if (t
[0]) { *error
= 1; return oe
; }
1798 return skipBlanks(expr
);
1802 ///////////////////////////////////////////////////////////////////////////////
1805 // for regsters & conditions: op->v will be set to reg number
1806 int urIsValidOp (URAOperand
*op
, uint16_t addr
, int opt
) {
1808 if (opt
== UO_NONE
) return op
->s
[0] == '\0';
1809 if (!op
->s
[0]) return 0;
1812 if (op
->special
|| op
->mem
) return 0;
1813 if (op
->defined
&& (op
->v
< -128 || op
->v
> 255)) return 0;
1816 if (op
->special
|| op
->mem
) return 0;
1817 if (op
->defined
&& (op
->v
< -32768 || op
->v
> 65535)) return 0;
1820 if (op
->special
|| op
->mem
) return 0;
1821 if (op
->defined
&& (op
->v
< -32768 || op
->v
> 65535)) return 0;
1822 if (op
->v
< 0) op
->v
= 65536+op
->v
;
1825 if (op
->special
|| op
->mem
) return 0;
1826 if (op
->defined
&& (op
->v
< -32768 || op
->v
> 65535)) return 0;
1827 if (!op
->defined
) op
->v
= addr
;
1828 if (op
->v
< 0) op
->v
= 65536+op
->v
;
1829 i
= op
->v
-((int)addr
+2);
1830 if (i
< -128 || i
> 127) return 0;
1834 if (op
->special
|| !op
->mem
) return 0;
1835 if (op
->defined
&& (op
->v
< -32768 || op
->v
> 65535)) return 0;
1836 if (op
->v
< 0) op
->v
= 65536+op
->v
;
1838 case UO_R8
: case UO_2R8
:
1839 if (op
->mem
&& !strcmp(op
->s
, "HL")) { /*strcpy(op->s, "M");*/ op
->v
= 6; return 1; }
1841 case UO_R8_NOM
: case UO_2R8_NOM
:
1842 if (!op
->special
|| op
->mem
|| op
->s
[1]) return 0;
1844 case 'B': op
->v
= 0; break;
1845 case 'C': op
->v
= 1; break;
1846 case 'D': op
->v
= 2; break;
1847 case 'E': op
->v
= 3; break;
1848 case 'H': op
->v
= 4; break;
1849 case 'L': op
->v
= 5; break;
1850 case 'A': op
->v
= 7; break;
1855 if (!op
->special
|| op
->mem
) return 0;
1856 return strcmp(op
->s
, "(C)")==0;
1857 case UO_PORTIMM
: /* mem, 'cause (n) */
1858 if (op
->special
|| !op
->mem
) return 0;
1860 if (op
->defined
&& (op
->v
< 0 || op
->v
> 255)) return 0;
1863 if (!op
->special
|| op
->mem
) return 0;
1864 if (!strcmp(op
->s
, "XH") || !strcmp(op
->s
, "HX") || !strcmp(op
->s
, "IXH")) return 1;
1867 if (!op
->special
|| op
->mem
) return 0;
1868 if (!strcmp(op
->s
, "XL") || !strcmp(op
->s
, "LX") || !strcmp(op
->s
, "IXL")) return 1;
1871 if (!op
->special
|| op
->mem
) return 0;
1872 if (!strcmp(op
->s
, "YH") || !strcmp(op
->s
, "HY") || !strcmp(op
->s
, "IYH")) return 1;
1875 if (!op
->special
|| op
->mem
) return 0;
1876 if (!strcmp(op
->s
, "YL") || !strcmp(op
->s
, "LY") || !strcmp(op
->s
, "IYL")) return 1;
1879 if (!op
->special
|| op
->mem
) return 0;
1880 if (!strcmp(op
->s
, "A")) return 1;
1883 if (!op
->special
|| op
->mem
) return 0;
1884 if (!strcmp(op
->s
, "R")) return 1;
1887 if (!op
->special
|| op
->mem
) return 0;
1888 if (!strcmp(op
->s
, "I")) return 1;
1891 if (!op
->special
|| op
->mem
|| !op
->s
[1] || op
->s
[2]) return 0;
1892 if (!strcmp(op
->s
, "BC")) { op
->v
= 0; return 1; }
1893 if (!strcmp(op
->s
, "DE")) { op
->v
= 1; return 1; }
1894 if (!strcmp(op
->s
, "HL")) { op
->v
= 2; return 1; }
1895 if (!strcmp(op
->s
, "SP")) { op
->v
= 3; return 1; }
1898 if (!op
->special
|| op
->mem
|| !op
->s
[1] || op
->s
[2]) return 0;
1899 if (!strcmp(op
->s
, "BC")) { op
->v
= 0; return 1; }
1900 if (!strcmp(op
->s
, "DE")) { op
->v
= 1; return 1; }
1901 if (!strcmp(op
->s
, "HL")) { op
->v
= 2; return 1; }
1902 if (!strcmp(op
->s
, "AF")) { op
->v
= 3; return 1; }
1905 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "AF")) return 0;
1909 if (!op
->special
|| op
->mem
|| (strcmp(op
->s
, "AF'") && strcmp(op
->s
, "AFX"))) return 0;
1913 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "BC")) return 0;
1917 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "DE")) return 0;
1921 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "HL")) return 0;
1925 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "IX")) return 0;
1929 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "IY")) return 0;
1933 if (!op
->special
|| op
->mem
|| strcmp(op
->s
, "SP")) return 0;
1937 if (!op
->special
|| !op
->mem
|| strcmp(op
->s
, "SP")) return 0;
1941 if (!op
->special
|| !op
->mem
|| strcmp(op
->s
, "BC")) return 0;
1945 if (!op
->special
|| !op
->mem
|| strcmp(op
->s
, "DE")) return 0;
1949 if (!op
->special
|| !op
->mem
|| strcmp(op
->s
, "HL")) return 0;
1953 if (!op
->special
|| !op
->mem
|| op
->ixy
!= 0xDDU
) return 0;
1954 if (op
->defined
&& (op
->v
< -128 || op
->v
> 127)) return 0;
1957 if (!op
->special
|| !op
->mem
|| op
->ixy
!= 0xFDU
) return 0;
1958 if (op
->defined
&& (op
->v
< -128 || op
->v
> 127)) return 0;
1961 if (!op
->special
|| !op
->mem
|| op
->ixy
!= 0xDDU
) return 0;
1962 if (op
->defined
&& op
->v
!= 0) return 0;
1965 if (!op
->special
|| !op
->mem
|| op
->ixy
!= 0xFDU
) return 0;
1966 if (op
->defined
&& op
->v
!= 0) return 0;
1969 if (!op
->special
|| op
->mem
|| strlen(op
->s
) > 2) return 0;
1970 if (!strcmp(op
->s
, "NZ")) { op
->v
= 0; return 1; }
1971 if (!strcmp(op
->s
, "Z")) { op
->v
= 1; return 1; }
1972 if (!strcmp(op
->s
, "NC")) { op
->v
= 2; return 1; }
1973 if (!strcmp(op
->s
, "C")) { op
->v
= 3; return 1; }
1976 if (!op
->special
|| op
->mem
|| strlen(op
->s
) > 2) return 0;
1977 if (!strcmp(op
->s
, "NZ")) { op
->v
= 0; return 1; }
1978 if (!strcmp(op
->s
, "Z")) { op
->v
= 1; return 1; }
1979 if (!strcmp(op
->s
, "NC")) { op
->v
= 2; return 1; }
1980 if (!strcmp(op
->s
, "C")) { op
->v
= 3; return 1; }
1981 if (!strcmp(op
->s
, "PO")) { op
->v
= 4; return 1; }
1982 if (!strcmp(op
->s
, "PE")) { op
->v
= 5; return 1; }
1983 if (!strcmp(op
->s
, "P")) { op
->v
= 6; return 1; }
1984 if (!strcmp(op
->s
, "M")) { op
->v
= 7; return 1; }
1987 if (op
->special
|| op
->mem
) return 0;
1988 if (op
->defined
&& (op
->v
< 0 || op
->v
> 7)) return 0;
1991 if (op
->special
|| op
->mem
) return 0;
1992 if (op
->defined
&& (op
->v
< 0 || op
->v
> 0x38 || (op
->v
&7))) return 0;
1996 if (op
->special
|| op
->mem
) return 0;
1997 if (op
->defined
&& op
->v
!= 0) return 0;
2000 if (op
->special
|| op
->mem
) return 0;
2001 if (op
->defined
&& op
->v
!= 1) return 0;
2004 if (op
->special
|| op
->mem
) return 0;
2005 if (op
->defined
&& op
->v
!= 2) return 0;
2012 // mem size should be at least 7 bytes
2013 // returns size of the assembled code
2014 // result <0 on error
2015 // understands comments
2016 int urAssembleOne (const char *expr
, uint16_t destaddr
, uint16_t addr
, const char **errpos
) {
2023 const URAsmCmdInfo
*cm
;
2024 uint32_t code
, mask
;
2025 int opcPos
; // opcode will be placed here
2027 void doOperand (int idx
) {
2028 const URAOperand
*op
= ops
+idx
;
2030 switch (cm
->ops
[idx
]) {
2034 buf
[len
++] = op
->v
&0xFFU
;
2039 buf
[len
++] = op
->v
&0xFFU
;
2040 buf
[len
++] = ((op
->v
&0xFFFFU
)>>8)&0xFFU
;
2044 code
|= op
->v
&0xFFU
;
2052 code
|= (op
->v
&0xFFU
)<<3;
2056 code
|= (op
->v
&0xFFU
)<<4;
2065 // <0: error; 0: ok; >0: last operand (ops[opix].parsed != 0: non-empty one)
2066 int parseOperand (int opidx
) {
2068 const char *oe
= expr
;
2070 expr
= urNextOperand(ops
+opidx
, expr
, addr
, &error
);
2071 if (error
) { if (errpos
) *errpos
= oe
; return URA_BAD_OPERAND
; }
2072 if (!expr
|| !expr
[0] || expr
[0] == ';' || expr
[0] == ':') return 1;
2073 if (*expr
!= ',') { if (errpos
) *errpos
= oe
; return URA_BAD_OPERAND
; }
2078 int genCode (void) {
2079 for (int pos
= URASM_MAX_COMMAND
; pos
>= 0; --pos
) {
2082 if (tkn
!= URASM_COMMANDS
[pos
].mnemo
) continue;
2083 for (f
= 0; f
< 3; ++f
) {
2084 if (!urIsValidOp(&ops
[f
], addr
, URASM_COMMANDS
[pos
].ops
[f
])) break;
2086 if (f
< 3) continue;
2087 // command found, generate code
2088 len
= 0; cm
= URASM_COMMANDS
+pos
;
2089 code
= cm
->code
; mask
= cm
->mask
;
2090 if ((code
&0xFFFFUL
) == 0xCBDDUL
|| (code
&0xFFFFUL
) == 0xCBFDUL
) {
2092 // emit unmasked code
2093 buf
[0] = (code
&0xFFU
); buf
[1] = 0xCBU
;
2094 for (f
= 0; f
< 3; ++f
) {
2095 if (cm
->ops
[f
] == UO_MIX
|| cm
->ops
[f
] == UO_MIY
) {
2096 if (ops
[f
].defined
&& (ops
[f
].v
< -128 || ops
[f
].v
> 127)) f
= -1;
2097 else if (ops
[f
].defined
) buf
[2] = ops
[f
].v
;
2101 if (f
< 0) continue; // not me
2103 code
>>= 24; mask
>>= 24;
2104 if ((mask
&0xFFUL
) != 0xFFUL
) {
2105 for (f
= 0; f
< 3; ++f
) if (cm
->ops
[f
] != UO_MIX
&& cm
->ops
[f
] != UO_MIY
) doOperand(f
);
2109 for (f
= 0; f
< len
; ++f
) { urPutByte(destaddr
++, buf
[f
]); ++addr
; }
2113 // emit unmasked code
2114 while ((mask
&0xFFUL
) == 0xFFUL
) {
2115 buf
[len
++] = code
&0xFFUL
;
2116 code
>>= 8; mask
>>= 8;
2118 //ASSERT((code&0xFFFFFF00UL) == 0);
2129 for (f
= 0; f
< len
; ++f
) { urPutByte(destaddr
++, buf
[f
]); ++addr
; }
2133 if (errpos
) *errpos
= oe
;
2134 return URA_BAD_INSTRUCTION
;
2137 int doPushPop (void) {
2140 for (f
= len
= 0; ; ++f
) {
2142 const char *oe
= expr
;
2143 int res
= parseOperand(0);
2145 if (res
< 0) return res
;
2147 if (f
== 0 && !ops
[0].parsed
) { *errpos
= oe
; return URA_BAD_INSTRUCTION
; }
2151 code
= (tkn
==UT_POP
? 0xC1U
: 0xC5U
);
2152 if (urIsValidOp(ops
, addr
, UO_R16A
)) {
2153 code
|= (ops
[0].v
&0xFFU
)<<4;
2154 urPutByte(destaddr
++, code
);
2157 } else if (urIsValidOp(ops
, addr
, UO_R16IX
)) {
2158 code
|= (ops
[0].v
&0xFFU
)<<4;
2159 urPutByte(destaddr
++, 0xDDU
);
2160 urPutByte(destaddr
++, code
);
2163 } else if (urIsValidOp(ops
, addr
, UO_R16IY
)) {
2164 code
|= (ops
[0].v
&0xFFU
)<<4;
2165 urPutByte(destaddr
++, 0xFDU
);
2166 urPutByte(destaddr
++, code
);
2170 if (errpos
) *errpos
= oe
;
2171 return URA_BAD_OPERAND
;
2177 expr
= skipBlanks(expr
);
2178 if (expr
[0] && expr
[0] != ';') {
2179 if (errpos
) *errpos
= expr
;
2180 if (expr
[0] != ':') return URA_EXTRA_TEXT
;
2186 int dorep (int opcnt
) {
2189 memset(ops
, 0, sizeof(ops
));
2190 for (f
= len
= 0; ; ++f
) {
2191 int doQuit
= 0, res
;
2194 for (int c
= 0; c
< opcnt
; ++c
) {
2196 res
= parseOperand(c
);
2197 if (res
< 0) return res
;
2199 if (c
!= opcnt
-1 || !ops
[c
].parsed
) { *errpos
= oe
; return URA_BAD_INSTRUCTION
; }
2204 if ((res
= genCode()) < 0) return res
;
2211 expr
= skipBlanks(expr
);
2212 if (expr
[0] && expr
[0] != ';') {
2213 if (errpos
) *errpos
= expr
;
2214 if (expr
[0] != ':') return URA_EXTRA_TEXT
;
2220 if (errpos
) *errpos
= NULL
;
2221 if (!urPutByte
|| !expr
) return URA_GENERIC
;
2223 expr
= skipBlanks(expr
);
2224 if (!expr
[0] || expr
[0] == ';') return 0;
2225 if (expr
[0] == ':') { if (errpos
) *errpos
= expr
; return 0; }
2226 for (oe
= expr
; *expr
&& !isspace(*expr
) && *expr
!= ':' && *expr
!= ';'; ++expr
) ;
2227 if (expr
-oe
> 4) { if (errpos
) *errpos
= oe
; return URA_BAD_MNEMO
; } // bad mnemonics
2229 memset(mnem
, 0, sizeof(mnem
));
2230 memcpy(mnem
, oe
, expr
-oe
);
2231 for (int f
= 0; mnem
[f
]; ++f
) mnem
[f
] = toupper(mnem
[f
]);
2233 for (tkn
= 0; tkn
< URASM_MAX_TOKEN
; ++tkn
) if (!strcmp(mnem
, URASM_TOKENS
[tkn
])) break;
2234 if (tkn
>= URASM_MAX_TOKEN
) { if (errpos
) *errpos
= oe
; return URA_BAD_MNEMO
; } // unknown mnemonics
2236 expr
= skipBlanks(expr
);
2237 if (expr
[0] == ',') { if (errpos
) *errpos
= oe
; return URA_BAD_OPERAND
; }
2238 /* special for PUSH and POP */
2239 if (tkn
== UT_POP
|| tkn
== UT_PUSH
) return doPushPop();
2240 /* special for LD */
2241 if (tkn
== UT_LD
|| tkn
== UT_ADD
|| tkn
== UT_ADC
|| tkn
== UT_SBC
) return dorep(2);
2242 /* special for RR/RL */
2243 if (tkn
== UT_RL
|| tkn
== UT_RR
|| tkn
== UT_INC
|| tkn
== UT_DEC
) return dorep(1);
2245 memset(ops
, 0, sizeof(ops
));
2246 for (int f
= 0; f
< 3; ++f
) {
2247 int res
= parseOperand(f
);
2250 if (res
< 0) return res
;
2254 expr
= skipBlanks(expr
);
2255 if (expr
[0] && expr
[0] != ';') {
2256 if (errpos
) *errpos
= expr
;
2257 if (expr
[0] != ':') return URA_EXTRA_TEXT
;
2265 static const char *msgs
[5] = {
2269 "extra text after instruction",
2274 const char *urErrorMessage (int errcode
) {
2275 if (errcode
>= 0) return "";
2276 if (errcode
< -5) return "unknown error";
2277 return msgs
[(-errcode
)-1];