1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * URASM: Z80 assembler/disassembler engine v0.0.2b
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 module iv
.zymosis
.urasm
/*is aliced*/;
22 //version = urasm_test;
25 // ////////////////////////////////////////////////////////////////////////// //
37 OUTD
, OUTI
, POP
, PUSH
,
44 XOR
, XSLT
, NOPX
, NOPY
,
47 // all possible operands
48 // there are so many for proper assembling
49 // (i wanted to do a simple table lookup w/o special cases, so all special cases were encoded as various operand types)
52 IMM8
, // immediate constant
53 IMM16
, // immediate constant
54 ADDR16
, // immediate address (JP/CALL)
55 ADDR8
, // immediate address (JR/DJNZ)
56 MEM16
, // immediate memory (nnnn)
57 // 8 bit registers (bits 0-2 of opcode)
58 R8
, // B,C,D,E,H,L,(HL),A
59 R8NOM
, // B,C,D,E,H,L,A (no (HL) )
60 // 8 bit registers (bits 3-5 of opcode)
61 R83
, // B,C,D,E,H,L,(HL),A
62 R83NOM
,// B,C,D,E,H,L,A (no (HL) )
66 // special 8 bit registers
74 // 16 bit registers (bits 4-5 of opcode)
76 // 16 bit registers (bits 4-5 of opcode)
78 // AF & AF' for EX AF,AF'
95 // JR condition (bits 3-4 of opcode)
97 // conditions (bits 3-5 of opcode)
99 // CB opcodes -- bit numbers (bits 3-5 of opcode)
101 // RST address (bits 3-5 of opcode <-- (address shr 3))
104 IM0
, // not necessary for IM, denotes any 0
105 IM1
, // not necessary for IM, denotes any 1
106 IM2
// not necessary for IM, denotes any 2
107 //IM01 // undocumented IM 0/1
110 // ////////////////////////////////////////////////////////////////////////// //
111 alias URFindLabelByAddrCB
= const(char)[] delegate (ushort addr
);
112 alias URGetByteCB
= ubyte delegate (ushort addr
);
118 bool decimal
; /// use decimal numbers in output?
124 const(char)[][3] ops
; // operands
128 void clear () pure nothrow @trusted @nogc { bufpos
= 0; mnem
= null; ops
[] = null; iidx
= 0; }
130 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline
, true); return (bufpos
> 0); }
132 /// get disassembled text; mnemonic delimited by '\t'
133 const(char)[] getbuf () const pure nothrow @trusted @nogc { pragma(inline
, true); return buf
[0..bufpos
]; }
135 /// get mnemonic text
136 const(char)[] getmnemo () const pure nothrow @trusted @nogc { pragma(inline
, true); return mnem
; }
139 const(char)[] getop (int idx
) const pure nothrow @trusted @nogc { pragma(inline
, true); return (idx
>= 0 && idx
< 3 ? ops
.ptr
[idx
] : null); }
141 /// get instruction index into `URInstructionsTable`
142 int itableidx () const pure nothrow @trusted @nogc { pragma(inline
, true); return iidx
; }
145 void resetbuf () nothrow @trusted @nogc { bufpos
= 0; }
147 void put (const(char)[] s
...) nothrow @trusted @nogc {
148 if (s
.length
> buf
.length
) s
= s
[0..buf
.length
];
149 if (bufpos
+cast(uint)s
.length
> buf
.length
) s
= s
[0..buf
.length
-bufpos
];
150 if (s
.length
== 0) return;
151 buf
[bufpos
..bufpos
+s
.length
] = s
[];
152 bufpos
+= cast(uint)s
.length
;
155 void putnum(T
) (string fmt
, T n
) nothrow @trusted @nogc {
156 import core
.stdc
.stdio
: snprintf
;
157 if (fmt
.length
> 32) assert(0, "wtf?!");
159 char[33] destbuf
= 0;
160 fmtbuf
[0..fmt
.length
] = fmt
[];
161 static if (T
.sizeof
<= 4) {
162 static if (__traits(isUnsigned
, T
)) {
163 auto len
= snprintf(destbuf
.ptr
, destbuf
.length
, fmtbuf
.ptr
, cast(uint)n
);
165 auto len
= snprintf(destbuf
.ptr
, destbuf
.length
, fmtbuf
.ptr
, cast(int)n
);
168 static assert(0, "wtf?!");
170 if (len
< 0) assert(0, "wtf?!");
171 put(destbuf
[0..len
]);
174 void putxnum(T
) (string fmth
, string fmtd
, T n
) nothrow @trusted @nogc {
175 putnum
!T((decimal ? fmtd
: fmth
), n
);
180 static immutable string
[URMnemo
.max
+1] URMnemonics
= [
181 "ADC", "ADD", "AND", "BIT", "CALL","CCF", "CP", "CPD",
182 "CPDR","CPI", "CPIR","CPL", "DAA", "DEC", "DI", "DJNZ",
183 "EI", "EX", "EXX", "HALT","IM", "IN", "INC", "IND",
184 "INDR","INI", "INIR","JP", "JR", "LD", "LDD", "LDDR",
185 "LDI", "LDIR","NEG", "NOP", "OR", "OTDR","OTIR","OUT",
186 "OUTD","OUTI","POP", "PUSH","RES", "RET", "RETI","RETN",
187 "RL", "RLA", "RLC", "RLCA","RLD", "RR", "RRA", "RRC",
188 "RRCA","RRD", "RST", "SBC", "SCF", "SET", "SLA", "SLI",
189 "SLL", "SRA", "SRL", "SUB", "XOR", "XSLT","NOPX","NOPY",
193 static immutable string
[8] URRegs8
= ["B","C","D","E","H","L","(HL)","A"];
194 static immutable string
[4] URRegs16
= ["BC","DE","HL","SP"];
195 static immutable string
[4] URRegs16a
= ["BC","DE","HL","AF"];
196 static immutable string
[8] URCond
= ["NZ","Z","NC","C","PO","PE","P","M"];
199 struct URAsmCmdInfo
{
201 uint code
; /// Z80 machine code
202 uint mask
; /// mask (for disassembler)
206 // the longest matches must come first (for disassembler)
207 // solid-masked must come first (for disassembler)
208 // assembler searches the table from the last command
209 // disassembler searches the table from the first command
210 // heh, i spent a whole night creating this shit! %-)
211 static immutable URAsmCmdInfo
[358] URInstructionsTable
= [
212 URAsmCmdInfo(URMnemo
.NOPX
, 0x000000DDU
, 0x00000000U
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
213 URAsmCmdInfo(URMnemo
.NOPY
, 0x000000FDU
, 0x00000000U
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
214 // DD/CB opcodes (special)
216 URAsmCmdInfo(URMnemo
.RLC
, 0x0600CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
218 URAsmCmdInfo(URMnemo
.RRC
, 0x0E00CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
220 URAsmCmdInfo(URMnemo
.RL
, 0x1600CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
222 URAsmCmdInfo(URMnemo
.RR
, 0x1E00CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
224 URAsmCmdInfo(URMnemo
.SLA
, 0x2600CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
226 URAsmCmdInfo(URMnemo
.SRA
, 0x2E00CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
228 URAsmCmdInfo(URMnemo
.SLL
, 0x3600CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
230 URAsmCmdInfo(URMnemo
.SLI
, 0x3600CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
232 URAsmCmdInfo(URMnemo
.SRL
, 0x3E00CBDDU
, 0xFF00FFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
234 URAsmCmdInfo(URMnemo
.RES
, 0x8600CBDDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.NONE
]),
236 URAsmCmdInfo(URMnemo
.SET
, 0xC600CBDDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.NONE
]),
237 // FD/CB opcodes (special)
239 URAsmCmdInfo(URMnemo
.RLC
, 0x0600CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
241 URAsmCmdInfo(URMnemo
.RRC
, 0x0E00CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
243 URAsmCmdInfo(URMnemo
.RL
, 0x1600CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
245 URAsmCmdInfo(URMnemo
.RR
, 0x1E00CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
247 URAsmCmdInfo(URMnemo
.SLA
, 0x2600CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
249 URAsmCmdInfo(URMnemo
.SRA
, 0x2E00CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
251 URAsmCmdInfo(URMnemo
.SLL
, 0x3600CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
253 URAsmCmdInfo(URMnemo
.SLI
, 0x3600CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
255 URAsmCmdInfo(URMnemo
.SRL
, 0x3E00CBFDU
, 0xFF00FFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
257 URAsmCmdInfo(URMnemo
.RES
, 0x8600CBFDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.NONE
]),
259 URAsmCmdInfo(URMnemo
.SET
, 0xC600CBFDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.NONE
]),
263 URAsmCmdInfo(URMnemo
.RLC
, 0x0000CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
265 URAsmCmdInfo(URMnemo
.RRC
, 0x0800CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
267 URAsmCmdInfo(URMnemo
.RL
, 0x1000CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
269 URAsmCmdInfo(URMnemo
.RR
, 0x1800CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
271 URAsmCmdInfo(URMnemo
.SLA
, 0x2000CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
273 URAsmCmdInfo(URMnemo
.SRA
, 0x2800CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
275 URAsmCmdInfo(URMnemo
.SLL
, 0x3000CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
277 URAsmCmdInfo(URMnemo
.SLI
, 0x3000CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
279 URAsmCmdInfo(URMnemo
.SRL
, 0x3800CBDDU
, 0xF800FFFFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
281 URAsmCmdInfo(URMnemo
.BIT
, 0x4600CBDDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.NONE
]),
283 URAsmCmdInfo(URMnemo
.BIT
, 0x4000CBDDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.R8NOM
]),
285 URAsmCmdInfo(URMnemo
.RES
, 0x8000CBDDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.R8NOM
]),
287 URAsmCmdInfo(URMnemo
.SET
, 0xC000CBDDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIX
, UROpType
.R8NOM
]),
290 URAsmCmdInfo(URMnemo
.RLC
, 0x0000CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
292 URAsmCmdInfo(URMnemo
.RRC
, 0x0800CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
294 URAsmCmdInfo(URMnemo
.RL
, 0x1000CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
296 URAsmCmdInfo(URMnemo
.RR
, 0x1800CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
298 URAsmCmdInfo(URMnemo
.SLA
, 0x2000CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
300 URAsmCmdInfo(URMnemo
.SRA
, 0x2800CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
302 URAsmCmdInfo(URMnemo
.SLL
, 0x3000CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
304 URAsmCmdInfo(URMnemo
.SLI
, 0x3000CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
306 URAsmCmdInfo(URMnemo
.SRL
, 0x3800CBFDU
, 0xF800FFFFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
308 URAsmCmdInfo(URMnemo
.BIT
, 0x4600CBFDU
, 0xC700FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.NONE
]),
310 URAsmCmdInfo(URMnemo
.BIT
, 0x4000CBFDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.R8NOM
]),
312 URAsmCmdInfo(URMnemo
.RES
, 0x8000CBFDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.R8NOM
]),
314 URAsmCmdInfo(URMnemo
.SET
, 0xC000CBFDU
, 0xC000FFFFU
, [UROpType
.BITN
, UROpType
.MIY
, UROpType
.R8NOM
]),
315 // standard CB opcodes
317 URAsmCmdInfo(URMnemo
.RLC
, 0x00CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
319 URAsmCmdInfo(URMnemo
.RRC
, 0x08CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
321 URAsmCmdInfo(URMnemo
.RL
, 0x10CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
323 URAsmCmdInfo(URMnemo
.RR
, 0x18CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
325 URAsmCmdInfo(URMnemo
.SLA
, 0x20CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
327 URAsmCmdInfo(URMnemo
.SRA
, 0x28CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
329 URAsmCmdInfo(URMnemo
.SLL
, 0x30CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
331 URAsmCmdInfo(URMnemo
.SLI
, 0x30CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
333 URAsmCmdInfo(URMnemo
.SRL
, 0x38CBU
, 0xF8FFU
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
335 URAsmCmdInfo(URMnemo
.BIT
, 0x40CBU
, 0xC0FFU
, [UROpType
.BITN
, UROpType
.R8
, UROpType
.NONE
]),
337 URAsmCmdInfo(URMnemo
.RES
, 0x80CBU
, 0xC0FFU
, [UROpType
.BITN
, UROpType
.R8
, UROpType
.NONE
]),
339 URAsmCmdInfo(URMnemo
.SET
, 0xC0CBU
, 0xC0FFU
, [UROpType
.BITN
, UROpType
.R8
, UROpType
.NONE
]),
343 URAsmCmdInfo(URMnemo
.XSLT
, 0xFBEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
344 // ED string instructions
345 URAsmCmdInfo(URMnemo
.LDI
, 0xA0EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
346 URAsmCmdInfo(URMnemo
.LDIR
, 0xB0EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
347 URAsmCmdInfo(URMnemo
.CPI
, 0xA1EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
348 URAsmCmdInfo(URMnemo
.CPIR
, 0xB1EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
349 URAsmCmdInfo(URMnemo
.INI
, 0xA2EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
350 URAsmCmdInfo(URMnemo
.INIR
, 0xB2EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
351 URAsmCmdInfo(URMnemo
.OUTI
, 0xA3EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
352 URAsmCmdInfo(URMnemo
.OTIR
, 0xB3EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
353 URAsmCmdInfo(URMnemo
.LDD
, 0xA8EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
354 URAsmCmdInfo(URMnemo
.LDDR
, 0xB8EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
355 URAsmCmdInfo(URMnemo
.CPD
, 0xA9EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
356 URAsmCmdInfo(URMnemo
.CPDR
, 0xB9EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
357 URAsmCmdInfo(URMnemo
.IND
, 0xAAEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
358 URAsmCmdInfo(URMnemo
.INDR
, 0xBAEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
359 URAsmCmdInfo(URMnemo
.OUTD
, 0xABEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
360 URAsmCmdInfo(URMnemo
.OTDR
, 0xBBEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
363 URAsmCmdInfo(URMnemo
.RRD
, 0x67EDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
364 URAsmCmdInfo(URMnemo
.RLD
, 0x6FEDU
, 0xFFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
367 URAsmCmdInfo(URMnemo
.IN
, 0x70EDU
, 0xFFFFU
, [UROpType
.PORTC
, UROpType
.NONE
, UROpType
.NONE
]),
369 URAsmCmdInfo(URMnemo
.OUT
, 0x71EDU
, 0xFFFFU
, [UROpType
.PORTC
, UROpType
.IM0
, UROpType
.NONE
]),
372 URAsmCmdInfo(URMnemo
.LD
, 0x47EDU
, 0xFFFFU
, [UROpType
.R8I
, UROpType
.R8A
, UROpType
.NONE
]),
374 URAsmCmdInfo(URMnemo
.LD
, 0x57EDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8I
, UROpType
.NONE
]),
376 URAsmCmdInfo(URMnemo
.LD
, 0x4FEDU
, 0xFFFFU
, [UROpType
.R8R
, UROpType
.R8A
, UROpType
.NONE
]),
378 URAsmCmdInfo(URMnemo
.LD
, 0x5FEDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8R
, UROpType
.NONE
]),
380 //(.mnemo=UT_IM, .code=0x4EEDU, .mask=0xFFFFU, .ops={UO_IM01, UO_NONE, UO_NONE}},
383 URAsmCmdInfo(URMnemo
.RETN
, 0x45EDU
, 0xCFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
384 URAsmCmdInfo(URMnemo
.RETI
, 0x4DEDU
, 0xCFFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
387 URAsmCmdInfo(URMnemo
.SBC
, 0x42EDU
, 0xCFFFU
, [UROpType
.R16HL
, UROpType
.R16
, UROpType
.NONE
]),
389 URAsmCmdInfo(URMnemo
.ADC
, 0x4AEDU
, 0xCFFFU
, [UROpType
.R16HL
, UROpType
.R16
, UROpType
.NONE
]),
391 URAsmCmdInfo(URMnemo
.LD
, 0x43EDU
, 0xCFFFU
, [UROpType
.MEM16
, UROpType
.R16
, UROpType
.NONE
]),
393 URAsmCmdInfo(URMnemo
.LD
, 0x4BEDU
, 0xCFFFU
, [UROpType
.R16
, UROpType
.MEM16
, UROpType
.NONE
]),
396 URAsmCmdInfo(URMnemo
.NEG
, 0x44EDU
, 0xC7FFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
399 URAsmCmdInfo(URMnemo
.IN
, 0x40EDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.PORTC
, UROpType
.NONE
]),
401 URAsmCmdInfo(URMnemo
.OUT
, 0x41EDU
, 0xC7FFU
, [UROpType
.PORTC
, UROpType
.R83NOM
, UROpType
.NONE
]),
404 URAsmCmdInfo(URMnemo
.IM
, 0x5EEDU
, 0xDFFFU
, [UROpType
.IM2
, UROpType
.NONE
, UROpType
.NONE
]),
406 URAsmCmdInfo(URMnemo
.IM
, 0x56EDU
, 0xDFFFU
, [UROpType
.IM1
, UROpType
.NONE
, UROpType
.NONE
]),
408 URAsmCmdInfo(URMnemo
.IM
, 0x46EDU
, 0xD7FFU
, [UROpType
.IM0
, UROpType
.NONE
, UROpType
.NONE
]),
411 URAsmCmdInfo(URMnemo
.LD
, 0xF9DDU
, 0xFFFFU
, [UROpType
.R16SP
, UROpType
.R16IX
, UROpType
.NONE
]),
413 URAsmCmdInfo(URMnemo
.LD
, 0xF9FDU
, 0xFFFFU
, [UROpType
.R16SP
, UROpType
.R16IY
, UROpType
.NONE
]),
416 URAsmCmdInfo(URMnemo
.EX
, 0xE3DDU
, 0xFFFFU
, [UROpType
.MSP
, UROpType
.R16IX
, UROpType
.NONE
]),
417 // EX IX,(SP) (ditto)
418 URAsmCmdInfo(URMnemo
.EX
, 0xE3DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.MSP
, UROpType
.NONE
]),
420 URAsmCmdInfo(URMnemo
.EX
, 0xE3FDU
, 0xFFFFU
, [UROpType
.MSP
, UROpType
.R16IY
, UROpType
.NONE
]),
421 // EX IY,(SP) (ditto)
422 URAsmCmdInfo(URMnemo
.EX
, 0xE3FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.MSP
, UROpType
.NONE
]),
425 URAsmCmdInfo(URMnemo
.JP
, 0xE9DDU
, 0xFFFFU
, [UROpType
.MIX0
, UROpType
.NONE
, UROpType
.NONE
]),
427 URAsmCmdInfo(URMnemo
.JP
, 0xE9FDU
, 0xFFFFU
, [UROpType
.MIY0
, UROpType
.NONE
, UROpType
.NONE
]),
429 URAsmCmdInfo(URMnemo
.JP
, 0xE9DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.NONE
, UROpType
.NONE
]),
431 URAsmCmdInfo(URMnemo
.JP
, 0xE9FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.NONE
, UROpType
.NONE
]),
434 URAsmCmdInfo(URMnemo
.POP
, 0xE1DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.NONE
, UROpType
.NONE
]),
436 URAsmCmdInfo(URMnemo
.PUSH
, 0xE5DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.NONE
, UROpType
.NONE
]),
438 URAsmCmdInfo(URMnemo
.POP
, 0xE1FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.NONE
, UROpType
.NONE
]),
440 URAsmCmdInfo(URMnemo
.PUSH
, 0xE5FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.NONE
, UROpType
.NONE
]),
443 URAsmCmdInfo(URMnemo
.ADD
, 0x86DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
445 URAsmCmdInfo(URMnemo
.ADD
, 0x86DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
447 URAsmCmdInfo(URMnemo
.ADC
, 0x8EDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
449 URAsmCmdInfo(URMnemo
.ADC
, 0x8EDDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
451 URAsmCmdInfo(URMnemo
.SUB
, 0x96DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
453 URAsmCmdInfo(URMnemo
.SUB
, 0x96DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
455 URAsmCmdInfo(URMnemo
.SBC
, 0x9EDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
457 URAsmCmdInfo(URMnemo
.SBC
, 0x9EDDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
459 URAsmCmdInfo(URMnemo
.AND
, 0xA6DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
461 URAsmCmdInfo(URMnemo
.AND
, 0xA6DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
463 URAsmCmdInfo(URMnemo
.XOR
, 0xAEDDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
465 URAsmCmdInfo(URMnemo
.XOR
, 0xAEDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
467 URAsmCmdInfo(URMnemo
.OR
, 0xB6DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
469 URAsmCmdInfo(URMnemo
.OR
, 0xB6DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
471 URAsmCmdInfo(URMnemo
.CP
, 0xBEDDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
473 URAsmCmdInfo(URMnemo
.CP
, 0xBEDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIX
, UROpType
.NONE
]),
475 URAsmCmdInfo(URMnemo
.ADD
, 0x86FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
477 URAsmCmdInfo(URMnemo
.ADD
, 0x86FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
479 URAsmCmdInfo(URMnemo
.ADC
, 0x8EFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
481 URAsmCmdInfo(URMnemo
.ADC
, 0x8EFDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
483 URAsmCmdInfo(URMnemo
.SUB
, 0x96FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
485 URAsmCmdInfo(URMnemo
.SUB
, 0x96FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
487 URAsmCmdInfo(URMnemo
.SBC
, 0x9EFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
489 URAsmCmdInfo(URMnemo
.SBC
, 0x9EFDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
491 URAsmCmdInfo(URMnemo
.AND
, 0xA6FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
493 URAsmCmdInfo(URMnemo
.AND
, 0xA6FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
495 URAsmCmdInfo(URMnemo
.XOR
, 0xAEFDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
497 URAsmCmdInfo(URMnemo
.XOR
, 0xAEFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
499 URAsmCmdInfo(URMnemo
.OR
, 0xB6FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
501 URAsmCmdInfo(URMnemo
.OR
, 0xB6FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
503 URAsmCmdInfo(URMnemo
.CP
, 0xBEFDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
505 URAsmCmdInfo(URMnemo
.CP
, 0xBEFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.MIY
, UROpType
.NONE
]),
507 URAsmCmdInfo(URMnemo
.ADD
, 0x84DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
509 URAsmCmdInfo(URMnemo
.ADD
, 0x84DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
511 URAsmCmdInfo(URMnemo
.ADC
, 0x8CDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
513 URAsmCmdInfo(URMnemo
.ADC
, 0x8CDDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
515 URAsmCmdInfo(URMnemo
.SUB
, 0x94DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
517 URAsmCmdInfo(URMnemo
.SUB
, 0x94DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
519 URAsmCmdInfo(URMnemo
.SBC
, 0x9CDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
521 URAsmCmdInfo(URMnemo
.SBC
, 0x9CDDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
523 URAsmCmdInfo(URMnemo
.AND
, 0xA4DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
525 URAsmCmdInfo(URMnemo
.AND
, 0xA4DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
527 URAsmCmdInfo(URMnemo
.XOR
, 0xACDDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
529 URAsmCmdInfo(URMnemo
.XOR
, 0xACDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
531 URAsmCmdInfo(URMnemo
.OR
, 0xB4DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
533 URAsmCmdInfo(URMnemo
.OR
, 0xB4DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
535 URAsmCmdInfo(URMnemo
.CP
, 0xBCDDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
537 URAsmCmdInfo(URMnemo
.CP
, 0xBCDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XH
, UROpType
.NONE
]),
539 URAsmCmdInfo(URMnemo
.ADD
, 0x85DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
541 URAsmCmdInfo(URMnemo
.ADD
, 0x85DDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
543 URAsmCmdInfo(URMnemo
.ADC
, 0x8DDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
545 URAsmCmdInfo(URMnemo
.ADC
, 0x8DDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
547 URAsmCmdInfo(URMnemo
.SUB
, 0x95DDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
549 URAsmCmdInfo(URMnemo
.SUB
, 0x95DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
551 URAsmCmdInfo(URMnemo
.SBC
, 0x9DDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
553 URAsmCmdInfo(URMnemo
.SBC
, 0x9DDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
555 URAsmCmdInfo(URMnemo
.AND
, 0xA5DDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
557 URAsmCmdInfo(URMnemo
.AND
, 0xA5DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
559 URAsmCmdInfo(URMnemo
.XOR
, 0xADDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
561 URAsmCmdInfo(URMnemo
.XOR
, 0xADDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
563 URAsmCmdInfo(URMnemo
.OR
, 0xB5DDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
565 URAsmCmdInfo(URMnemo
.OR
, 0xB5DDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
567 URAsmCmdInfo(URMnemo
.CP
, 0xBDDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
569 URAsmCmdInfo(URMnemo
.CP
, 0xBDDDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8XL
, UROpType
.NONE
]),
571 URAsmCmdInfo(URMnemo
.ADD
, 0x84FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
573 URAsmCmdInfo(URMnemo
.ADD
, 0x84FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
575 URAsmCmdInfo(URMnemo
.ADC
, 0x8CFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
577 URAsmCmdInfo(URMnemo
.ADC
, 0x8CFDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
579 URAsmCmdInfo(URMnemo
.SUB
, 0x94FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
581 URAsmCmdInfo(URMnemo
.SUB
, 0x94FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
583 URAsmCmdInfo(URMnemo
.SBC
, 0x9CFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
585 URAsmCmdInfo(URMnemo
.SBC
, 0x9CFDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
587 URAsmCmdInfo(URMnemo
.AND
, 0xA4FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
589 URAsmCmdInfo(URMnemo
.AND
, 0xA4FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
591 URAsmCmdInfo(URMnemo
.XOR
, 0xACFDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
593 URAsmCmdInfo(URMnemo
.XOR
, 0xACFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
595 URAsmCmdInfo(URMnemo
.OR
, 0xB4FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
597 URAsmCmdInfo(URMnemo
.OR
, 0xB4FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
599 URAsmCmdInfo(URMnemo
.CP
, 0xBCFDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
601 URAsmCmdInfo(URMnemo
.CP
, 0xBCFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YH
, UROpType
.NONE
]),
603 URAsmCmdInfo(URMnemo
.ADD
, 0x85FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
605 URAsmCmdInfo(URMnemo
.ADD
, 0x85FDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
607 URAsmCmdInfo(URMnemo
.ADC
, 0x8DFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
609 URAsmCmdInfo(URMnemo
.ADC
, 0x8DFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
611 URAsmCmdInfo(URMnemo
.SUB
, 0x95FDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
613 URAsmCmdInfo(URMnemo
.SUB
, 0x95FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
615 URAsmCmdInfo(URMnemo
.SBC
, 0x9DFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
617 URAsmCmdInfo(URMnemo
.SBC
, 0x9DFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
619 URAsmCmdInfo(URMnemo
.AND
, 0xA5FDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
621 URAsmCmdInfo(URMnemo
.AND
, 0xA5FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
623 URAsmCmdInfo(URMnemo
.XOR
, 0xADFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
625 URAsmCmdInfo(URMnemo
.XOR
, 0xADFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
627 URAsmCmdInfo(URMnemo
.OR
, 0xB5FDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
629 URAsmCmdInfo(URMnemo
.OR
, 0xB5FDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
631 URAsmCmdInfo(URMnemo
.CP
, 0xBDFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
633 URAsmCmdInfo(URMnemo
.CP
, 0xBDFDU
, 0xFFFFU
, [UROpType
.R8A
, UROpType
.R8YL
, UROpType
.NONE
]),
636 URAsmCmdInfo(URMnemo
.LD
, 0x64DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.R8XH
, UROpType
.NONE
]),
638 URAsmCmdInfo(URMnemo
.LD
, 0x65DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.R8XL
, UROpType
.NONE
]),
640 URAsmCmdInfo(URMnemo
.LD
, 0x6CDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.R8XH
, UROpType
.NONE
]),
642 URAsmCmdInfo(URMnemo
.LD
, 0x6DDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.R8XL
, UROpType
.NONE
]),
644 URAsmCmdInfo(URMnemo
.LD
, 0x64FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.R8YH
, UROpType
.NONE
]),
646 URAsmCmdInfo(URMnemo
.LD
, 0x65FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.R8YL
, UROpType
.NONE
]),
648 URAsmCmdInfo(URMnemo
.LD
, 0x6CFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.R8YH
, UROpType
.NONE
]),
650 URAsmCmdInfo(URMnemo
.LD
, 0x6DFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.R8YL
, UROpType
.NONE
]),
653 URAsmCmdInfo(URMnemo
.LD
, 0x22DDU
, 0xFFFFU
, [UROpType
.MEM16
, UROpType
.R16IX
, UROpType
.NONE
]),
655 URAsmCmdInfo(URMnemo
.LD
, 0x2ADDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.MEM16
, UROpType
.NONE
]),
657 URAsmCmdInfo(URMnemo
.LD
, 0x22FDU
, 0xFFFFU
, [UROpType
.MEM16
, UROpType
.R16IY
, UROpType
.NONE
]),
659 URAsmCmdInfo(URMnemo
.LD
, 0x2AFDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.MEM16
, UROpType
.NONE
]),
662 URAsmCmdInfo(URMnemo
.LD
, 0x21DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.IMM16
, UROpType
.NONE
]),
664 URAsmCmdInfo(URMnemo
.LD
, 0x21FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.IMM16
, UROpType
.NONE
]),
667 URAsmCmdInfo(URMnemo
.INC
, 0x23DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.NONE
, UROpType
.NONE
]),
669 URAsmCmdInfo(URMnemo
.DEC
, 0x2BDDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.NONE
, UROpType
.NONE
]),
671 URAsmCmdInfo(URMnemo
.INC
, 0x23FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.NONE
, UROpType
.NONE
]),
673 URAsmCmdInfo(URMnemo
.DEC
, 0x2BFDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.NONE
, UROpType
.NONE
]),
676 URAsmCmdInfo(URMnemo
.INC
, 0x34DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
678 URAsmCmdInfo(URMnemo
.DEC
, 0x35DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.NONE
, UROpType
.NONE
]),
680 URAsmCmdInfo(URMnemo
.LD
, 0x36DDU
, 0xFFFFU
, [UROpType
.MIX
, UROpType
.IMM8
, UROpType
.NONE
]),
682 URAsmCmdInfo(URMnemo
.INC
, 0x34FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
684 URAsmCmdInfo(URMnemo
.DEC
, 0x35FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.NONE
, UROpType
.NONE
]),
686 URAsmCmdInfo(URMnemo
.LD
, 0x36FDU
, 0xFFFFU
, [UROpType
.MIY
, UROpType
.IMM8
, UROpType
.NONE
]),
689 URAsmCmdInfo(URMnemo
.INC
, 0x24DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
691 URAsmCmdInfo(URMnemo
.DEC
, 0x25DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.NONE
, UROpType
.NONE
]),
693 URAsmCmdInfo(URMnemo
.INC
, 0x2CDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
695 URAsmCmdInfo(URMnemo
.DEC
, 0x2DDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.NONE
, UROpType
.NONE
]),
697 URAsmCmdInfo(URMnemo
.INC
, 0x24FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
699 URAsmCmdInfo(URMnemo
.DEC
, 0x25FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.NONE
, UROpType
.NONE
]),
701 URAsmCmdInfo(URMnemo
.INC
, 0x2CFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
703 URAsmCmdInfo(URMnemo
.DEC
, 0x2DFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.NONE
, UROpType
.NONE
]),
706 URAsmCmdInfo(URMnemo
.LD
, 0x26DDU
, 0xFFFFU
, [UROpType
.R8XH
, UROpType
.IMM8
, UROpType
.NONE
]),
708 URAsmCmdInfo(URMnemo
.LD
, 0x2EDDU
, 0xFFFFU
, [UROpType
.R8XL
, UROpType
.IMM8
, UROpType
.NONE
]),
710 URAsmCmdInfo(URMnemo
.LD
, 0x26FDU
, 0xFFFFU
, [UROpType
.R8YH
, UROpType
.IMM8
, UROpType
.NONE
]),
712 URAsmCmdInfo(URMnemo
.LD
, 0x2EFDU
, 0xFFFFU
, [UROpType
.R8YL
, UROpType
.IMM8
, UROpType
.NONE
]),
715 URAsmCmdInfo(URMnemo
.ADD
, 0x09DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.R16BC
, UROpType
.NONE
]),
717 URAsmCmdInfo(URMnemo
.ADD
, 0x19DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.R16DE
, UROpType
.NONE
]),
719 URAsmCmdInfo(URMnemo
.ADD
, 0x29DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.R16IX
, UROpType
.NONE
]),
721 URAsmCmdInfo(URMnemo
.ADD
, 0x39DDU
, 0xFFFFU
, [UROpType
.R16IX
, UROpType
.R16SP
, UROpType
.NONE
]),
723 URAsmCmdInfo(URMnemo
.ADD
, 0x09FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.R16BC
, UROpType
.NONE
]),
725 URAsmCmdInfo(URMnemo
.ADD
, 0x19FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.R16DE
, UROpType
.NONE
]),
727 URAsmCmdInfo(URMnemo
.ADD
, 0x29FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.R16IY
, UROpType
.NONE
]),
729 URAsmCmdInfo(URMnemo
.ADD
, 0x39FDU
, 0xFFFFU
, [UROpType
.R16IY
, UROpType
.R16SP
, UROpType
.NONE
]),
732 URAsmCmdInfo(URMnemo
.LD
, 0x60DDU
, 0xF8FFU
, [UROpType
.R8XH
, UROpType
.R8NOM
, UROpType
.NONE
]),
734 URAsmCmdInfo(URMnemo
.LD
, 0x68DDU
, 0xF8FFU
, [UROpType
.R8XL
, UROpType
.R8NOM
, UROpType
.NONE
]),
736 URAsmCmdInfo(URMnemo
.LD
, 0x70DDU
, 0xF8FFU
, [UROpType
.MIX
, UROpType
.R8NOM
, UROpType
.NONE
]),
738 URAsmCmdInfo(URMnemo
.LD
, 0x60FDU
, 0xF8FFU
, [UROpType
.R8YH
, UROpType
.R8NOM
, UROpType
.NONE
]),
740 URAsmCmdInfo(URMnemo
.LD
, 0x68FDU
, 0xF8FFU
, [UROpType
.R8YL
, UROpType
.R8NOM
, UROpType
.NONE
]),
742 URAsmCmdInfo(URMnemo
.LD
, 0x70FDU
, 0xF8FFU
, [UROpType
.MIY
, UROpType
.R8NOM
, UROpType
.NONE
]),
745 URAsmCmdInfo(URMnemo
.LD
, 0x44DDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.R8XH
, UROpType
.NONE
]),
747 URAsmCmdInfo(URMnemo
.LD
, 0x45DDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.R8XL
, UROpType
.NONE
]),
749 URAsmCmdInfo(URMnemo
.LD
, 0x46DDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.MIX
, UROpType
.NONE
]),
752 URAsmCmdInfo(URMnemo
.LD
, 0x44FDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.R8YH
, UROpType
.NONE
]),
754 URAsmCmdInfo(URMnemo
.LD
, 0x45FDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.R8YL
, UROpType
.NONE
]),
756 URAsmCmdInfo(URMnemo
.LD
, 0x46FDU
, 0xC7FFU
, [UROpType
.R83NOM
, UROpType
.MIY
, UROpType
.NONE
]),
758 // instructions w/o operands or with unchangeable operands
759 URAsmCmdInfo(URMnemo
.NOP
, 0x00U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
760 URAsmCmdInfo(URMnemo
.RLCA
, 0x07U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
761 URAsmCmdInfo(URMnemo
.RRCA
, 0x0FU
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
762 URAsmCmdInfo(URMnemo
.RLA
, 0x17U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
763 URAsmCmdInfo(URMnemo
.RRA
, 0x1FU
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
764 URAsmCmdInfo(URMnemo
.DAA
, 0x27U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
765 URAsmCmdInfo(URMnemo
.CPL
, 0x2FU
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
766 URAsmCmdInfo(URMnemo
.SCF
, 0x37U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
767 URAsmCmdInfo(URMnemo
.CCF
, 0x3FU
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
768 URAsmCmdInfo(URMnemo
.HALT
, 0x76U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
769 URAsmCmdInfo(URMnemo
.RET
, 0xC9U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
770 URAsmCmdInfo(URMnemo
.EXX
, 0xD9U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
771 URAsmCmdInfo(URMnemo
.DI
, 0xF3U
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
772 URAsmCmdInfo(URMnemo
.EI
, 0xFBU
, 0xFFU
, [UROpType
.NONE
, UROpType
.NONE
, UROpType
.NONE
]),
774 URAsmCmdInfo(URMnemo
.LD
, 0xF9U
, 0xFFU
, [UROpType
.R16SP
, UROpType
.R16HL
, UROpType
.NONE
]),
776 URAsmCmdInfo(URMnemo
.EX
, 0x08U
, 0xFFU
, [UROpType
.R16AF
, UROpType
.R16AFX
, UROpType
.NONE
]),
778 URAsmCmdInfo(URMnemo
.EX
, 0x08U
, 0xFFU
, [UROpType
.R16AFX
, UROpType
.R16AF
, UROpType
.NONE
]),
780 URAsmCmdInfo(URMnemo
.EX
, 0xE3U
, 0xFFU
, [UROpType
.MSP
, UROpType
.R16HL
, UROpType
.NONE
]),
781 // EX HL,(SP) (ditto)
782 URAsmCmdInfo(URMnemo
.EX
, 0xE3U
, 0xFFU
, [UROpType
.R16HL
, UROpType
.MSP
, UROpType
.NONE
]),
784 URAsmCmdInfo(URMnemo
.EX
, 0xEBU
, 0xFFU
, [UROpType
.R16DE
, UROpType
.R16HL
, UROpType
.NONE
]),
786 URAsmCmdInfo(URMnemo
.EX
, 0xEBU
, 0xFFU
, [UROpType
.R16HL
, UROpType
.R16DE
, UROpType
.NONE
]),
788 URAsmCmdInfo(URMnemo
.JP
, 0xE9U
, 0xFFU
, [UROpType
.MHL
, UROpType
.NONE
, UROpType
.NONE
]),
790 URAsmCmdInfo(URMnemo
.JP
, 0xE9U
, 0xFFU
, [UROpType
.R16HL
, UROpType
.NONE
, UROpType
.NONE
]),
792 URAsmCmdInfo(URMnemo
.JP
, 0xC3U
, 0xFFU
, [UROpType
.ADDR16
, UROpType
.NONE
, UROpType
.NONE
]),
794 URAsmCmdInfo(URMnemo
.CALL
, 0xCDU
, 0xFFU
, [UROpType
.ADDR16
, UROpType
.NONE
, UROpType
.NONE
]),
796 URAsmCmdInfo(URMnemo
.OUT
, 0xD3U
, 0xFFU
, [UROpType
.PORTIMM
, UROpType
.R8A
, UROpType
.NONE
]),
798 URAsmCmdInfo(URMnemo
.IN
, 0xDBU
, 0xFFU
, [UROpType
.R8A
, UROpType
.PORTIMM
, UROpType
.NONE
]),
801 URAsmCmdInfo(URMnemo
.ADD
, 0xC6U
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
803 URAsmCmdInfo(URMnemo
.ADD
, 0xC6U
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
805 URAsmCmdInfo(URMnemo
.ADC
, 0xCEU
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
807 URAsmCmdInfo(URMnemo
.ADC
, 0xCEU
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
809 URAsmCmdInfo(URMnemo
.SUB
, 0xD6U
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
811 URAsmCmdInfo(URMnemo
.SUB
, 0xD6U
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
813 URAsmCmdInfo(URMnemo
.SBC
, 0xDEU
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
815 URAsmCmdInfo(URMnemo
.SBC
, 0xDEU
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
817 URAsmCmdInfo(URMnemo
.AND
, 0xE6U
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
819 URAsmCmdInfo(URMnemo
.AND
, 0xE6U
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
821 URAsmCmdInfo(URMnemo
.XOR
, 0xEEU
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
823 URAsmCmdInfo(URMnemo
.XOR
, 0xEEU
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
825 URAsmCmdInfo(URMnemo
.OR
, 0xF6U
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
827 URAsmCmdInfo(URMnemo
.OR
, 0xF6U
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
829 URAsmCmdInfo(URMnemo
.CP
, 0xFEU
, 0xFFU
, [UROpType
.IMM8
, UROpType
.NONE
, UROpType
.NONE
]),
831 URAsmCmdInfo(URMnemo
.CP
, 0xFEU
, 0xFFU
, [UROpType
.R8A
, UROpType
.IMM8
, UROpType
.NONE
]),
833 URAsmCmdInfo(URMnemo
.LD
, 0x02U
, 0xFFU
, [UROpType
.MBC
, UROpType
.R8A
, UROpType
.NONE
]),
835 URAsmCmdInfo(URMnemo
.LD
, 0x12U
, 0xFFU
, [UROpType
.MDE
, UROpType
.R8A
, UROpType
.NONE
]),
837 URAsmCmdInfo(URMnemo
.LD
, 0x0AU
, 0xFFU
, [UROpType
.R8A
, UROpType
.MBC
, UROpType
.NONE
]),
839 URAsmCmdInfo(URMnemo
.LD
, 0x1AU
, 0xFFU
, [UROpType
.R8A
, UROpType
.MDE
, UROpType
.NONE
]),
841 URAsmCmdInfo(URMnemo
.LD
, 0x22U
, 0xFFU
, [UROpType
.MEM16
, UROpType
.R16HL
, UROpType
.NONE
]),
843 URAsmCmdInfo(URMnemo
.LD
, 0x2AU
, 0xFFU
, [UROpType
.R16HL
, UROpType
.MEM16
, UROpType
.NONE
]),
845 URAsmCmdInfo(URMnemo
.LD
, 0x32U
, 0xFFU
, [UROpType
.MEM16
, UROpType
.R8A
, UROpType
.NONE
]),
847 URAsmCmdInfo(URMnemo
.LD
, 0x3AU
, 0xFFU
, [UROpType
.R8A
, UROpType
.MEM16
, UROpType
.NONE
]),
849 URAsmCmdInfo(URMnemo
.DJNZ
, 0x10U
, 0xFFU
, [UROpType
.ADDR8
, UROpType
.NONE
, UROpType
.NONE
]),
851 URAsmCmdInfo(URMnemo
.JR
, 0x18U
, 0xFFU
, [UROpType
.ADDR8
, UROpType
.NONE
, UROpType
.NONE
]),
854 URAsmCmdInfo(URMnemo
.ADD
, 0x09U
, 0xCFU
, [UROpType
.R16HL
, UROpType
.R16
, UROpType
.NONE
]),
857 URAsmCmdInfo(URMnemo
.ADD
, 0x80U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
859 URAsmCmdInfo(URMnemo
.ADD
, 0x80U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
861 URAsmCmdInfo(URMnemo
.ADC
, 0x88U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
863 URAsmCmdInfo(URMnemo
.ADC
, 0x88U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
865 URAsmCmdInfo(URMnemo
.SUB
, 0x90U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
867 URAsmCmdInfo(URMnemo
.SUB
, 0x90U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
869 URAsmCmdInfo(URMnemo
.SBC
, 0x98U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
871 URAsmCmdInfo(URMnemo
.SBC
, 0x98U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
873 URAsmCmdInfo(URMnemo
.AND
, 0xA0U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
875 URAsmCmdInfo(URMnemo
.AND
, 0xA0U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
877 URAsmCmdInfo(URMnemo
.XOR
, 0xA8U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
879 URAsmCmdInfo(URMnemo
.XOR
, 0xA8U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
881 URAsmCmdInfo(URMnemo
.OR
, 0xB0U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
883 URAsmCmdInfo(URMnemo
.OR
, 0xB0U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
885 URAsmCmdInfo(URMnemo
.CP
, 0xB8U
, 0xF8U
, [UROpType
.R8
, UROpType
.NONE
, UROpType
.NONE
]),
887 URAsmCmdInfo(URMnemo
.CP
, 0xB8U
, 0xF8U
, [UROpType
.R8A
, UROpType
.R8
, UROpType
.NONE
]),
890 URAsmCmdInfo(URMnemo
.JR
, 0x20U
, 0xE7U
, [UROpType
.JRCOND
, UROpType
.ADDR8
, UROpType
.NONE
]),
893 URAsmCmdInfo(URMnemo
.POP
, 0xC1U
, 0xCFU
, [UROpType
.R16A
, UROpType
.NONE
, UROpType
.NONE
]),
895 URAsmCmdInfo(URMnemo
.PUSH
, 0xC5U
, 0xCFU
, [UROpType
.R16A
, UROpType
.NONE
, UROpType
.NONE
]),
897 URAsmCmdInfo(URMnemo
.RET
, 0xC0U
, 0xC7U
, [UROpType
.COND
, UROpType
.NONE
, UROpType
.NONE
]),
899 URAsmCmdInfo(URMnemo
.JP
, 0xC2U
, 0xC7U
, [UROpType
.COND
, UROpType
.ADDR16
, UROpType
.NONE
]),
901 URAsmCmdInfo(URMnemo
.CALL
, 0xC4U
, 0xC7U
, [UROpType
.COND
, UROpType
.ADDR16
, UROpType
.NONE
]),
903 URAsmCmdInfo(URMnemo
.RST
, 0xC7U
, 0xC7U
, [UROpType
.RSTDEST
, UROpType
.NONE
, UROpType
.NONE
]),
906 URAsmCmdInfo(URMnemo
.INC
, 0x04U
, 0xC7U
, [UROpType
.R83
, UROpType
.NONE
, UROpType
.NONE
]),
908 URAsmCmdInfo(URMnemo
.DEC
, 0x05U
, 0xC7U
, [UROpType
.R83
, UROpType
.NONE
, UROpType
.NONE
]),
910 URAsmCmdInfo(URMnemo
.LD
, 0x06U
, 0xC7U
, [UROpType
.R83
, UROpType
.IMM8
, UROpType
.NONE
]),
913 URAsmCmdInfo(URMnemo
.LD
, 0x01U
, 0xCFU
, [UROpType
.R16
, UROpType
.IMM16
, UROpType
.NONE
]),
915 URAsmCmdInfo(URMnemo
.INC
, 0x03U
, 0xCFU
, [UROpType
.R16
, UROpType
.NONE
, UROpType
.NONE
]),
917 URAsmCmdInfo(URMnemo
.DEC
, 0x0BU
, 0xCFU
, [UROpType
.R16
, UROpType
.NONE
, UROpType
.NONE
]),
920 URAsmCmdInfo(URMnemo
.LD
, 0x40U
, 0xC0U
, [UROpType
.R83
, UROpType
.R8
, UROpType
.NONE
]),
924 URAsmCmdInfo(URMnemo
.LD
, 0x4940U
, 0xFFFFU
, [UROpType
.R16BC
, UROpType
.R16BC
, UROpType
.NONE
]),
926 URAsmCmdInfo(URMnemo
.LD
, 0x4B42U
, 0xFFFFU
, [UROpType
.R16BC
, UROpType
.R16DE
, UROpType
.NONE
]),
928 URAsmCmdInfo(URMnemo
.LD
, 0x4D44U
, 0xFFFFU
, [UROpType
.R16BC
, UROpType
.R16HL
, UROpType
.NONE
]),
930 URAsmCmdInfo(URMnemo
.LD
, 0x5950U
, 0xFFFFU
, [UROpType
.R16DE
, UROpType
.R16BC
, UROpType
.NONE
]),
932 URAsmCmdInfo(URMnemo
.LD
, 0x5B52U
, 0xFFFFU
, [UROpType
.R16DE
, UROpType
.R16DE
, UROpType
.NONE
]),
934 URAsmCmdInfo(URMnemo
.LD
, 0x5D54U
, 0xFFFFU
, [UROpType
.R16DE
, UROpType
.R16HL
, UROpType
.NONE
]),
936 URAsmCmdInfo(URMnemo
.LD
, 0x6960U
, 0xFFFFU
, [UROpType
.R16HL
, UROpType
.R16BC
, UROpType
.NONE
]),
938 URAsmCmdInfo(URMnemo
.LD
, 0x6B62U
, 0xFFFFU
, [UROpType
.R16HL
, UROpType
.R16DE
, UROpType
.NONE
]),
940 URAsmCmdInfo(URMnemo
.LD
, 0x6D64U
, 0xFFFFU
, [UROpType
.R16HL
, UROpType
.R16HL
, UROpType
.NONE
]),
944 // instructions unaffected by DD/FF prefixes
945 // this table used by disassembler (we don't want to eat prefixes)
946 static immutable ubyte[256] URIgnoreDDFDTable
= [
947 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
948 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
949 1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,
950 1,1,1,1,0,0,0,1,1,0,1,1,1,1,1,1,
951 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
952 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
953 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
954 0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,1,
955 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
956 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
957 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
958 1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,1,
959 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
960 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
961 1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,
962 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,
967 // ////////////////////////////////////////////////////////////////////////// //
970 private bool isDDSensitive (uint c
) pure nothrow @trusted @nogc { pragma(inline
, true); return (URIgnoreDDFDTable
.ptr
[c
&0xff] != 0); }
973 // nextW: next 2 bytes (after opcode)
974 // idx: I? displacement
975 void urdisOp2Str (ref URDisState ctx
, int op
, ushort addr
, ubyte opc
, ushort nextW
, int idx
, scope URFindLabelByAddrCB findLabel
) {
976 import core
.stdc
.stdio
: sprintf
;
977 //int add, ismem = 0;
980 case UROpType
.NONE
: break;
981 case UROpType
.IMM8
: ctx
.putxnum("#%02X", "%u", nextW
&0xFF); break;
982 case UROpType
.IMM16
: ctx
.putxnum("#%04X", "%u", nextW
); break;
986 int add = (nextW
< 128 ? nextW
: (cast(int)nextW
)-256);
990 case UROpType
.ADDR16
:
991 if (findLabel
!is null) {
992 auto lbl
= findLabel(nextW
);
993 if (lbl
.length
) { ctx
.put(lbl
); break; }
994 lbl
= findLabel(cast(ushort)(nextW
-1));
995 if (lbl
.length
) { ctx
.put(lbl
); ctx
.put("-1"); break; }
996 lbl
= findLabel(cast(ushort)(nextW
-2));
997 if (lbl
.length
) { ctx
.put(lbl
); ctx
.put("-2"); break; }
998 lbl
= findLabel(cast(ushort)(nextW
+1));
999 if (lbl
.length
) { ctx
.put(lbl
); ctx
.put("+1"); break; }
1000 lbl
= findLabel(cast(ushort)(nextW
+2));
1001 if (lbl
.length
) { ctx
.put(lbl
); ctx
.put("+2"); break; }
1003 ctx
.putxnum("#%04X", "%u", nextW
);
1005 case UROpType
.MEM16
:
1008 goto case UROpType
.ADDR16
;
1010 case UROpType
.R8NOM
:
1011 ctx
.put(URRegs8
.ptr
[opc
&0x07UL
]);
1014 case UROpType
.R83NOM
:
1015 ctx
.put(URRegs8
.ptr
[(opc
>>3)&0x07UL
]);
1017 case UROpType
.PORTC
: ctx
.put("(C)"); break;
1018 case UROpType
.PORTIMM
: ctx
.putxnum("(#%02X)", "(%u)", nextW
&0xFF); break;
1019 case UROpType
.R8XH
: ctx
.put("XH"); break;
1020 case UROpType
.R8XL
: ctx
.put("XL"); break;
1021 case UROpType
.R8YH
: ctx
.put("YH"); break;
1022 case UROpType
.R8YL
: ctx
.put("YL"); break;
1023 case UROpType
.R8A
: ctx
.put("A"); break;
1024 case UROpType
.R8R
: ctx
.put("R"); break;
1025 case UROpType
.R8I
: ctx
.put("I"); break;
1026 case UROpType
.R16
: ctx
.put(URRegs16
.ptr
[(opc
>>4)&0x03UL
]); break;
1027 case UROpType
.R16A
: ctx
.put(URRegs16a
.ptr
[(opc
>>4)&0x03UL
]); break;
1028 case UROpType
.R16AF
: ctx
.put("AF"); break;
1029 case UROpType
.R16AFX
: ctx
.put("AF'"); break;
1030 case UROpType
.R16BC
: ctx
.put("BC"); break;
1031 case UROpType
.R16DE
: ctx
.put("DE"); break;
1032 case UROpType
.R16HL
: ctx
.put("HL"); break;
1033 case UROpType
.R16IX
: ctx
.put("IX"); break;
1034 case UROpType
.R16IY
: ctx
.put("IY"); break;
1035 case UROpType
.R16SP
: ctx
.put("SP"); break;
1036 case UROpType
.MSP
: ctx
.put("(SP)"); break;
1037 case UROpType
.MBC
: ctx
.put("(BC)"); break;
1038 case UROpType
.MDE
: ctx
.put("(DE)"); break;
1039 case UROpType
.MHL
: ctx
.put("(HL)"); break;
1040 case UROpType
.MIX0
: ctx
.put("(IX)"); break;
1041 case UROpType
.MIY0
: ctx
.put("(IY)"); break;
1044 if (idx
> 0) ctx
.put("+");
1045 ctx
.putnum("%d", idx
);
1050 if (idx
> 0) ctx
.put("+");
1051 ctx
.putnum("%d", idx
);
1054 case UROpType
.JRCOND
: ctx
.put(URCond
.ptr
[(opc
>>3)&0x03U
]); break;
1055 case UROpType
.COND
: ctx
.put(URCond
.ptr
[(opc
>>3)&0x07U
]); break;
1056 case UROpType
.BITN
: ctx
.putnum("%u", (opc
>>3)&0x07U
); break;
1057 case UROpType
.RSTDEST
: ctx
.putxnum("#%02X", "%u", opc
&0x38U
); break;
1058 case UROpType
.IM0
: ctx
.put("0"); break;
1059 case UROpType
.IM1
: ctx
.put("1"); break;
1060 case UROpType
.IM2
: ctx
.put("2"); break;
1061 default: assert(0); // we should never come here
1063 if (ismem
) ctx
.put(")");
1067 /// find the corresponding record in URInstructionsTable
1068 public int urDisassembleFind (ref URDisState ctx
, ushort addr
, scope URGetByteCB getByte
) {
1070 if (getByte
is null) return -1;
1071 foreach (immutable n
, ref ubyte b
; buf
[]) b
= getByte(cast(ushort)(addr
+n
));
1072 if (buf
.ptr
[0] == 0xDDU || buf
.ptr
[0] == 0xFDU
) {
1074 if (isDDSensitive(buf
.ptr
[1])) return (buf
.ptr
[0] == 0xDDU ?
0 : 1);
1076 uint ci
= buf
.ptr
[0]|
(buf
.ptr
[1]<<8)|
(buf
.ptr
[2]<<16)|
(buf
.ptr
[3]<<24);
1077 for (int opn
= 0; opn
< URInstructionsTable
.length
; ++opn
) {
1079 while (opn
< URInstructionsTable
.length
&& (ci
&URInstructionsTable
.ptr
[opn
].mask
) != URInstructionsTable
.ptr
[opn
].code
) ++opn
;
1080 if (opn
>= URInstructionsTable
.length
) return (buf
.ptr
[0] == 0xEDU ?
-2 : -1);
1081 // skip prefixes, determine command length
1082 uint f
= URInstructionsTable
.ptr
[opn
].mask
;
1083 uint c
= URInstructionsTable
.ptr
[opn
].code
;
1086 if ((f
&0xFFUL
) != 0xFFUL
) break;
1088 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
1092 // are there any operands?
1093 if (URInstructionsTable
.ptr
[opn
].ops
.ptr
[0] == UROpType
.NONE
) return opn
;
1094 // is this CB-prefixed?
1095 if ((URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBDDUL ||
1096 (URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
) ++bpos
; // skip displacement
1097 ubyte opc
= buf
.ptr
[bpos
];
1099 foreach (immutable n
; 0..4) {
1100 if (n
== 4) return cast(int)opn
;
1101 auto op
= URInstructionsTable
.ptr
[opn
].ops
.ptr
[n
];
1102 if (op
== UROpType
.NONE
) return cast(int)opn
;
1103 // check for valid operand
1104 if (op
== UROpType
.R8NOM
) {
1105 if ((opc
&0x07U
) == 6) break; // bad (HL)
1107 if (op
== UROpType
.R83NOM
) {
1108 if (((opc
>>3)&0x07U
) == 6) break; // bad (HL)
1116 /// length of the instruction with the given record (returned from `urDisassembleFind()`)
1117 public int urDisassembleLength (int idx
) {
1118 if (idx
== -2) return 2;
1119 if (idx
< 0 || idx
>= URInstructionsTable
.length
) return 1;
1120 if (idx
< 2) return 1;
1122 uint m
= URInstructionsTable
.ptr
[idx
].mask
;
1123 uint c
= URInstructionsTable
.ptr
[idx
].code
;
1125 //if ((m&0xFFFFUL) == 0xFFFFUL && (c&0xFF00UL) == 0xCBUL && ((c&0xFFUL) == 0xDDUL || (c&0xFFUL) == 0xFDUL)) return 4;
1126 // skip prefixes, determine command length
1129 if ((m
&0xFFUL
) != 0xFFUL
) break;
1131 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
1135 // is this CB-prefixed?
1136 if ((URInstructionsTable
.ptr
[idx
].code
&0xFFFFUL
) == 0xCBDDUL ||
1137 (URInstructionsTable
.ptr
[idx
].code
&0xFFFFUL
) == 0xCBFDUL
) m
>>= 8;
1139 while (m
!= 0) { m
>>= 8; ++res
; }
1141 oploop
: foreach (immutable n
; 0..3) {
1142 auto op
= URInstructionsTable
.ptr
[idx
].ops
.ptr
[n
];
1144 case UROpType
.NONE
: break oploop
;
1145 // command with displacement
1146 case UROpType
.MIX
: case UROpType
.MIY
: ++res
; break;
1147 // command has immediate operand
1148 case UROpType
.IMM8
: case UROpType
.ADDR8
: case UROpType
.PORTIMM
: ++res
; break;
1149 case UROpType
.IMM16
: case UROpType
.ADDR16
: case UROpType
.MEM16
: res
+= 2; break;
1157 /// disassemble one command, return command length or <0 on error
1158 public int urDisassembleOne (ref URDisState ctx
, ushort addr
, scope URGetByteCB getByte
, scope URFindLabelByAddrCB findLabel
=null) {
1168 scope(failure
) ctx
.clear();
1170 if (getByte
is null) return -1;
1171 foreach (immutable n
, ref ubyte b
; buf
[]) b
= getByte(cast(ushort)(addr
+n
));
1173 if (buf
.ptr
[0] == 0xDDU || buf
.ptr
[0] == 0xFDU
) {
1175 if (isDDSensitive(buf
.ptr
[1])) {
1176 ctx
.iidx
= (buf
.ptr
[0] == 0xDDU ?
0 : 1);
1177 ctx
.put(URMnemonics
.ptr
[buf
.ptr
[0] == 0xDDU ? URMnemo
.NOPX
: URMnemo
.NOPY
]);
1178 ctx
.mnem
= ctx
.buf
[0..ctx
.bufpos
];
1181 // take possible I? displacement
1182 idx
= cast(byte)buf
.ptr
[2];
1184 ci
= buf
.ptr
[0]|
(buf
.ptr
[1]<<8)|
(buf
.ptr
[2]<<16)|
(buf
.ptr
[3]<<24);
1185 for (opn
= 0; opn
< URInstructionsTable
.length
; ++opn
) {
1189 for (; opn
< URInstructionsTable
.length
&& (ci
&URInstructionsTable
.ptr
[opn
].mask
) != URInstructionsTable
.ptr
[opn
].code
; ++opn
) {}
1190 if (opn
>= URInstructionsTable
.length
) {
1193 ctx
.mnem
= ctx
.buf
[0..ctx
.bufpos
-1];
1194 auto opstp
= ctx
.bufpos
;
1195 if (buf
.ptr
[0] == 0xEDU
) {
1196 ctx
.putxnum("#%02X,", "%u,", buf
.ptr
[0]);
1197 ctx
.ops
[0] = ctx
.buf
[opstp
..ctx
.bufpos
-1];
1199 ctx
.putxnum("#%02X", "%u", buf
.ptr
[1]);
1200 ctx
.ops
[1] = ctx
.buf
[opstp
..ctx
.bufpos
];
1203 ctx
.putxnum("#%02X", "%u", buf
.ptr
[0]);
1204 ctx
.ops
[0] = ctx
.buf
[opstp
..ctx
.bufpos
];
1208 // skip prefixes, determine command length
1209 f
= URInstructionsTable
.ptr
[opn
].mask
;
1210 c
= URInstructionsTable
.ptr
[opn
].code
;
1211 for (bpos
= 0; ; ++bpos
) {
1212 if ((f
&0xFFUL
) != 0xFFUL
) break;
1214 if (b
!= 0xFDU
&& b
!= 0xDDU
&& b
!= 0xEDU
&& b
!= 0xCBU
) break;
1219 // is this CB-prefixed?
1220 if ((URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBDDUL ||
1221 (URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
) f
>>= 8;
1222 while (f
!= 0) { f
>>= 8; ++res
; }
1225 ctx
.put(URMnemonics
.ptr
[URInstructionsTable
.ptr
[opn
].mnemo
]);
1226 ctx
.mnem
= ctx
.buf
[0..ctx
.bufpos
];
1227 // are there any operands?
1228 if (URInstructionsTable
.ptr
[opn
].ops
.ptr
[0] == UROpType
.NONE
) return res
;
1229 // is this CB-prefixed?
1230 if (((URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBDDUL
) ||
1231 ((URInstructionsTable
.ptr
[opn
].code
&0xFFFFUL
) == 0xCBFDUL
)) {
1232 ++bpos
; // skip displacement
1234 if ((URInstructionsTable
.ptr
[opn
].ops
.ptr
[0] == UROpType
.MIX || URInstructionsTable
.ptr
[opn
].ops
.ptr
[0] == UROpType
.MIY
) &&
1235 URInstructionsTable
.ptr
[opn
].ops
.ptr
[1] == UROpType
.IMM8
&&
1236 URInstructionsTable
.ptr
[opn
].ops
.ptr
[2] == UROpType
.NONE
) ++bpos
; // skip displacement
1238 opc
= buf
.ptr
[bpos
++];
1239 nextW
= cast(ushort)(buf
.ptr
[bpos
]|
(buf
.ptr
[bpos
+1]<<8));
1241 foreach (immutable n
; 0..4) {
1242 if (n
== 3) return res
;
1243 op
= URInstructionsTable
.ptr
[opn
].ops
.ptr
[n
];
1244 if (op
== UROpType
.NONE
) return res
;
1245 // check for valid operand
1246 if (op
== UROpType
.R8NOM
) {
1247 if ((opc
&0x07U
) == 6) break; // bad (HL)
1249 if (op
== UROpType
.R83NOM
) {
1250 if (((opc
>>3)&0x07U
) == 6) break; // bad (HL)
1252 // command with displacement?
1253 if (op
== UROpType
.MIX || op
== UROpType
.MIY
) ++res
;
1254 // command has immediate operand?
1255 if (op
== UROpType
.IMM8 || op
== UROpType
.ADDR8 || op
== UROpType
.PORTIMM
) ++res
;
1256 if (op
== UROpType
.IMM16 || op
== UROpType
.ADDR16 || op
== UROpType
.MEM16
) res
+= 2;
1258 ctx
.put(n ?
"," : "\t");
1260 auto opstp
= ctx
.bufpos
;
1261 urdisOp2Str(ctx
, op
, addr
, opc
, nextW
, idx
, findLabel
);
1262 ctx
.ops
[n
] = ctx
.buf
[opstp
..ctx
.bufpos
];
1269 // ////////////////////////////////////////////////////////////////////////// //
1271 public struct URAsmParser
{
1276 pure nothrow @trusted @nogc:
1277 this (const(char)[] atext
) { text
= atext
; }
1278 void setup (const(char)[] atext
) { text
= atext
; }
1279 URAsmParser
opSlice (uint lo
, uint hi
) pure const {
1280 if (hi
<= lo || lo
>= text
.length
) return URAsmParser
.init
;
1281 if (hi
> text
.length
) hi
= cast(uint)text
.length
;
1282 return URAsmParser(text
[lo
..hi
]);
1284 @property uint tell () pure const { pragma(inline
, true); return textpos
; }
1285 void seek (uint pos
) pure { pragma(inline
, true); if (pos
> text
.length
) pos
= cast(uint)text
.length
; textpos
= pos
; }
1286 URAsmParser
slice (uint len
) pure const {
1287 if (len
> text
.length
) len
= cast(uint)text
.length
;
1288 if (textpos
>= text
.length
) return URAsmParser
.init
;
1289 if (text
.length
-textpos
< len
) len
= cast(uint)text
.length
-textpos
;
1290 return URAsmParser(text
[textpos
..textpos
+len
]);
1292 @property bool empty () const { pragma(inline
, true); return (textpos
>= text
.length
); }
1293 @property bool eol () const { pragma(inline
, true); return (textpos
>= text
.length || text
.ptr
[textpos
] == ':' || text
.ptr
[textpos
] == ';'); }
1294 @property char front () const { pragma(inline
, true); return (textpos
< text
.length ? text
.ptr
[textpos
] : '\x00'); }
1295 @property char ahead () const { pragma(inline
, true); return (textpos
+1 < text
.length ? text
.ptr
[textpos
+1] : '\x00'); }
1296 @property char peek (uint ofs
) const { pragma(inline
, true); return (ofs
< text
.length
&& textpos
+ofs
< text
.length ? text
.ptr
[textpos
+ofs
] : '\x00'); }
1297 void popFront () { if (textpos
< text
.length
) ++textpos
; }
1298 void skipBlanks () { while (textpos
< text
.length
&& text
.ptr
[textpos
] <= ' ') ++textpos
; }
1301 char tolower (char ch
) { pragma(inline
, true); return (ch
>= 'A' && ch
<= 'Z' ?
cast(char)(ch
+32) : ch
); }
1302 char toupper (char ch
) { pragma(inline
, true); return (ch
>= 'a' && ch
<= 'z' ?
cast(char)(ch
-32) : ch
); }
1303 bool isdigit (char ch
) { pragma(inline
, true); return (ch
>= '0' && ch
<= '9'); }
1304 bool isalpha (char ch
) { pragma(inline
, true); return (ch
>= 'A' && ch
<= 'Z') ||
(ch
>= 'a' && ch
<= 'z'); }
1305 bool isalnum (char ch
) { pragma(inline
, true); return (ch
>= 'A' && ch
<= 'Z') ||
(ch
>= 'a' && ch
<= 'z') ||
(ch
>= '0' && ch
<= '9'); }
1307 int digitInBase (char ch
, int base
=10) {
1308 pragma(inline
, true);
1310 ch
>= '0' && ch
<= '9' && ch
-'0' < base ? ch
-'0' :
1311 base
> 10 && ch
>= 'A' && ch
< 'Z' && ch
-'A'+10 < base ? ch
-'A'+10 :
1312 base
> 10 && ch
>= 'a' && ch
< 'z' && ch
-'a'+10 < base ? ch
-'a'+10 :
1316 bool strEquCI (const(char)[] s0
, const(char)[] s1
) {
1317 if (s0
.length
!= s1
.length
) return false;
1318 foreach (immutable idx
, char c0
; s0
) {
1319 if (c0
>= 'a' && c0
<= 'z') c0
-= 32;
1320 char c1
= s1
.ptr
[idx
];
1321 if (c1
>= 'a' && c1
<= 'z') c1
-= 32;
1322 if (c0
!= c1
) return false;
1329 // ////////////////////////////////////////////////////////////////////////// //
1331 public bool delegate (const(char)[] lbl
) nothrow @trusted @nogc urIsValidLabelName
;
1333 static this () { import std
.functional
: toDelegate
; urIsValidLabelName
= toDelegate(&urIsValidLabelNameDef
); }
1336 public bool urIsValidLabelNameDef (const(char)[] lbl
) nothrow @trusted @nogc {
1337 if (lbl
.length
== 0) return false;
1338 if (URAsmParser
.isalpha(lbl
.ptr
[0])) {
1339 foreach (char ch
; lbl
[1..$]) {
1340 if (ch
< 128 && !URAsmParser
.isalnum(ch
) && ch
!= '$' && ch
!= '.' && ch
!= '_' && ch
!= '@') return false;
1342 foreach (string s
; URMnemonics
) if (URAsmParser
.strEquCI(s
, lbl
)) return false;
1343 foreach (string s
; URRegs8
) if (URAsmParser
.strEquCI(s
, lbl
)) return false;
1344 foreach (string s
; URRegs16
) if (URAsmParser
.strEquCI(s
, lbl
)) return false;
1345 foreach (string s
; URRegs16a
) if (URAsmParser
.strEquCI(s
, lbl
)) return false;
1346 foreach (string s
; URCond
) if (URAsmParser
.strEquCI(s
, lbl
)) return false;
1347 if (URAsmParser
.strEquCI("DB", lbl
)) return false;
1348 if (URAsmParser
.strEquCI("DW", lbl
)) return false;
1349 if (URAsmParser
.strEquCI("DS", lbl
)) return false;
1350 if (URAsmParser
.strEquCI("DZ", lbl
)) return false;
1351 if (URAsmParser
.strEquCI("DEFB", lbl
)) return false;
1352 if (URAsmParser
.strEquCI("DEFW", lbl
)) return false;
1353 if (URAsmParser
.strEquCI("DEFS", lbl
)) return false;
1354 if (URAsmParser
.strEquCI("DEFZ", lbl
)) return false;
1355 if (URAsmParser
.strEquCI("DEFM", lbl
)) return false;
1356 if (URAsmParser
.strEquCI("ORG", lbl
)) return false;
1357 if (URAsmParser
.strEquCI("ENT", lbl
)) return false;
1359 if (lbl
.ptr
[0] != '$' && lbl
.ptr
[0] != '.' && lbl
.ptr
[0] != '_' && lbl
.ptr
[0] != '@') return false;
1360 foreach (char ch
; lbl
[1..$]) {
1361 if (ch
< 128 && !URAsmParser
.isalnum(ch
) && ch
!= '$' && ch
!= '.' && ch
!= '_' && ch
!= '@') return false;
1368 // ////////////////////////////////////////////////////////////////////////// //
1370 public enum URAsmFixup
{
1378 public int delegate (const(char)[] lbl
, ushort addr
, out bool defined
, out URAsmFixup fixtype
) urFindLabelByNameFn
; ///
1380 /// pr is right after '(', spaces skipped; should parse all args and stop on closing ')'
1381 public void delegate (const(char)[] lbl
, ref URAsmParser pr
, out URExprValue res
, ushort addr
) urCallFunctionFn
;
1383 /// get "special value" started with '*' or '=', pr is right after valtype, spaces skipped; should parse whole name
1384 public void delegate (char valtype
, ref URAsmParser pr
, out URExprValue res
, ushort addr
) urGetValueFn
;
1387 enum URAsmExprError
{
1404 static immutable string
[URAsmExprError
.max
+1] URAsmExprErrorMsg
= [
1406 "unexpected end of text",
1408 "unbalanced parentheses",
1413 "function expected",
1415 "invalid special argument",
1417 "invalid memory access",
1421 void EERROR (URAsmExprError code
) { throw new Exception("urasm expression error: "~URAsmExprErrorMsg
[code
]); }
1424 // ////////////////////////////////////////////////////////////////////////// //
1425 /// expression parser
1426 public struct URExprValue
{
1428 char[] str; /// null: non-string value; val is set for strings too
1429 URAsmFixup fixuptype
; /// can be changed only by low() and high()
1430 bool defined
= true;
1432 @property bool isString () const pure nothrow @trusted @nogc { pragma(inline
, true); return (str !is null); } ///
1434 void clear () pure nothrow @trusted @nogc { val
= 0; str = null; fixuptype
= URAsmFixup
.None
; defined
= true; } ///
1438 UROpType type
; // deduced type
1439 char[] s
; // string value, if any
1440 int v
; // expression value or index
1441 bool defined
; // expression defined?
1442 URAsmFixup fixuptype
;
1444 string
toString () const {
1445 import std
.format
: format
;
1446 return "<%s>: v=%d; defined=%s".format(type
, v
, defined
);
1452 ushort addr
; // current address
1453 bool defined
; // true: all used labels are defined
1459 // do math; op0 is the result
1460 alias ExprDoItFn
= void function (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
);
1462 struct ExprOperator
{
1463 char sn
; // short name or 0
1464 string ln
; // long name or null if `sn`!=0
1465 int prio
; // priority
1470 void propagateFixup (ref URExprValue op0
, ref URExprValue op1
) {
1471 if (op0
.fixuptype
== URAsmFixup
.None
) {
1472 op0
.fixuptype
= op1
.fixuptype
;
1473 } else if (op0
.fixuptype
== URAsmFixup
.Word
) {
1474 if (op1
.fixuptype
!= URAsmFixup
.None
) op0
.fixuptype
= op1
.fixuptype
;
1475 } else if (op1
.fixuptype
!= URAsmFixup
.None
&& op0
.fixuptype
!= op1
.fixuptype
) {
1478 EERROR(URAsmExprError
.Fixup
);
1483 void mdoBitNot (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) {
1485 op0
.fixuptype
= URAsmFixup
.None
;
1487 void mdoLogNot (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) {
1489 op0
.fixuptype
= URAsmFixup
.None
;
1491 void mdoBitAnd (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) {
1493 if (op1
.val
== 0) op0
.fixuptype
= URAsmFixup
.None
;
1494 else if (op0
.fixuptype
!= URAsmFixup
.None
) {
1496 case 0x00ff: op0
.fixuptype
= (op0
.fixuptype
== URAsmFixup
.Word ? URAsmFixup
.LoByte
: URAsmFixup
.None
); break;
1497 case 0xff00: op0
.fixuptype
= (op0
.fixuptype
== URAsmFixup
.Word ? URAsmFixup
.HiByte
: URAsmFixup
.None
); break;
1501 propagateFixup(op0
, op1
);
1504 void mdoBitOr (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val |
= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1505 void mdoBitXor (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val ^
= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1506 void mdoLShift (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
<<= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1507 void mdoRShift (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
>>= op1
.val
; }
1508 void mdoMul (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
*= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1509 void mdoDiv (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { if (op1
.val
== 0) EERROR(URAsmExprError
.Div0
); op0
.val
/= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1510 void mdoMod (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { if (op1
.val
== 0) EERROR(URAsmExprError
.Div0
); op0
.val
%= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1511 void mdoAdd (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
+= op1
.val
; propagateFixup(op0
, op1
); }
1512 void mdoSub (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
-= op1
.val
; propagateFixup(op0
, op1
); }
1513 void mdoLogLess (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
< op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1514 void mdoLogGreat (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
> op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1515 void mdoLogEqu (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
== op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1516 void mdoLogNEqu (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
!= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1517 void mdoLogLEqu (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
>= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1518 void mdoLogGEqu (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { op0
.val
= op0
.val
>= op1
.val
; op0
.fixuptype
= URAsmFixup
.None
; }
1519 void mdoLogAnd (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { ei
.logRes
= op0
.val
= (op0
.val
&& op1
.val
); if (!op0
.val
) ei
.logDone
= 1; op0
.fixuptype
= URAsmFixup
.None
; }
1520 void mdoLogOr (ref URExprValue op0
, ref URExprValue op1
, ref ExprInfo ei
) { ei
.logRes
= op0
.val
= (op0
.val || op1
.val
); if (op0
.val
) ei
.logDone
= 1; op0
.fixuptype
= URAsmFixup
.None
; }
1523 // priority level 1 -- opertiors like "." and "[]", function calls
1524 // priority level 2 -- unary opertiors like "!" and "~"
1525 // short forms must be put before long
1526 // priorities must be sorted
1527 static immutable ExprOperator
[23] operators
= [
1528 ExprOperator('~', null, 2, &mdoBitNot
),
1529 ExprOperator('!', null, 2, &mdoLogNot
),
1531 ExprOperator(0, "<<", 3, &mdoLShift
),
1532 ExprOperator(0, ">>", 3, &mdoRShift
),
1534 ExprOperator('&', null, 4, &mdoBitAnd
),
1536 ExprOperator('|', null, 5, &mdoBitOr
),
1537 ExprOperator('^', null, 5, &mdoBitXor
),
1539 ExprOperator('*', null, 6, &mdoMul
),
1540 ExprOperator('/', null, 6, &mdoDiv
),
1541 ExprOperator('%', null, 6, &mdoMod
),
1543 ExprOperator('+', null, 7, &mdoAdd
),
1544 ExprOperator('-', null, 7, &mdoSub
),
1546 ExprOperator(0, "&&", 8, &mdoLogAnd
),
1548 ExprOperator(0, "||", 9, &mdoLogOr
),
1550 ExprOperator('<', null, 10, &mdoLogLess
),
1551 ExprOperator('>', null, 10, &mdoLogGreat
),
1552 ExprOperator('=', null, 10, &mdoLogEqu
),
1553 ExprOperator(0, "==", 10, &mdoLogEqu
),
1554 ExprOperator(0, "!=", 10, &mdoLogNEqu
),
1555 ExprOperator(0, "<>", 10, &mdoLogNEqu
),
1556 ExprOperator(0, "<=", 10, &mdoLogLEqu
),
1557 ExprOperator(0, ">=", 10, &mdoLogGEqu
),
1558 ExprOperator(0, null, -1, null),
1560 enum UnaryPriority
= 2;
1561 enum MaxPriority
= operators
[$-2].prio
;
1562 // WARNING! keep this in sync with operator table!
1563 enum LogAndPriority
= 8;
1564 enum LogOrPriority
= 9;
1567 ///////////////////////////////////////////////////////////////////////////////
1568 // expression parser engine
1570 // quote is not skipped
1571 void parseStr (ref URAsmParser pr
, ref URExprValue res
) {
1574 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1575 char qch
= pr
.front
;
1578 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1582 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1586 case 'a': rstr
~= '\a'; break;
1587 case 'b': rstr
~= '\b'; break;
1588 case 'e': rstr
~= '\x1b'; break;
1589 case 'f': rstr
~= '\f'; break;
1590 case 'n': rstr
~= '\n'; break;
1591 case 'r': rstr
~= '\r'; break;
1592 case 't': rstr
~= '\t'; break;
1593 case 'v': rstr
~= '\v'; break;
1594 case 'z': rstr
~= '\0'; break;
1595 case 'x': case 'X': // hex
1599 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1600 for (n
= 0; f
> 0; --f
) {
1601 if (pr
.empty
) break;
1602 int d
= URAsmParser
.digitInBase(pr
.front
, base
);
1607 rstr
~= cast(char)n
;
1613 case '1': .. case '9': // decimal
1617 default: rstr
~= ch
; break; // others
1620 if (ch
== qch
) break;
1624 if (rstr
.length
== 0) { rstr
.length
= 1; rstr
.length
= 0; } // so it won't be null
1629 void parseNumber (ref URAsmParser pr
, ref URExprValue res
) {
1630 int n
= 0, base
= 0, nhex
= 0;
1631 bool wantTrailingH
= false;
1632 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1637 // this can be 0x prefix
1639 case '0': .. case '9': EERROR(URAsmExprError
.Number
); assert(0); // no octals
1640 case 'B': case 'b': base
= 2; pr
.popFront(); pr
.popFront(); break;
1641 case 'O': case 'o': base
= 8; pr
.popFront(); pr
.popFront(); break;
1642 case 'D': case 'd': base
= 10; pr
.popFront(); pr
.popFront(); break;
1643 case 'X': case 'x': base
= 16; pr
.popFront(); pr
.popFront(); break;
1647 case '%': base
= 2; pr
.popFront(); break;
1648 case '#': case '$': base
= 16; pr
.popFront(); break;
1651 case 'B': case 'b': base
= 2; pr
.popFront(); pr
.popFront(); break;
1652 case 'O': case 'o': base
= 8; pr
.popFront(); pr
.popFront(); break;
1653 case 'D': case 'd': base
= 10; pr
.popFront(); pr
.popFront(); break;
1654 case 'X': case 'x': base
= 16; pr
.popFront(); pr
.popFront(); break;
1655 case 'H': case 'h': base
= 16; pr
.popFront(); pr
.popFront(); break;
1656 default: EERROR(URAsmExprError
.Number
); // no octals
1661 // if base != 0, parse in dec and in hex, and check last char
1662 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1663 if (URAsmParser
.digitInBase(pr
.front
, (base ? base
: 16)) < 0) EERROR(URAsmExprError
.Number
);
1667 if (ch
== '_') { pr
.popFront(); continue; }
1669 d
= URAsmParser
.digitInBase(ch
, base
);
1673 if (wantTrailingH
) {
1674 d
= URAsmParser
.digitInBase(ch
, 16);
1678 d
= URAsmParser
.digitInBase(ch
, 10);
1680 d
= URAsmParser
.digitInBase(ch
, 16);
1682 wantTrailingH
= true;
1693 if (wantTrailingH
) {
1694 if (pr
.empty ||
(pr
.front
!= 'H' && pr
.front
!= 'h')) EERROR(URAsmExprError
.Number
);
1697 if (!pr
.empty
&& (pr
.front
== 'H' || pr
.front
== 'h')) { n
= nhex
; pr
.popFront(); }
1704 void getAddr (const(char)[] lbl
, ref URExprValue res
, ref ExprInfo ei
) {
1705 if (urFindLabelByNameFn
is null) EERROR(URAsmExprError
.Label
);
1706 res
.fixuptype
= URAsmFixup
.None
;
1707 res
.val
= urFindLabelByNameFn(lbl
, ei
.addr
, res
.defined
, res
.fixuptype
);
1708 if (!res
.defined
) ei
.defined
= false;
1712 // throw on invalid label, or return slice of `dbuf`
1713 char[] readLabelName (char[] dbuf
, ref URAsmParser pr
) {
1717 if (URAsmParser
.isalnum(ch
) || ch
== '$' || ch
== '.' || ch
== '_' || ch
== '@' || ch
>= 128) {
1718 if (dbpos
>= dbuf
.length
) EERROR(URAsmExprError
.Label
);
1725 if (dbpos
< 1 ||
!urIsValidLabelName(dbuf
[0..dbpos
])) EERROR(URAsmExprError
.Label
);
1726 return dbuf
[0..dbpos
];
1730 void term (ref URAsmParser pr
, ref URExprValue res
, ref ExprInfo ei
) {
1733 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1738 ch
= (ch
== '[' ?
']' : ')');
1739 expression(pr
, res
, ei
);
1740 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1741 if (pr
.front
!= ch
) EERROR(URAsmExprError
.Parens
);
1744 case '0': .. case '9': case '#': case '%':
1745 parseNumber(pr
, res
);
1748 if (URAsmParser
.digitInBase(pr
.ahead
, 16) >= 0) {
1749 parseNumber(pr
, res
);
1752 res
.fixuptype
= URAsmFixup
.Word
;
1762 parseNumber(pr
, res
);
1767 case '"': // char or 2 chars
1768 case '\'': // char or 2 reversed chars
1771 if (res
.str.length
== 1) {
1772 res
.val
= cast(ubyte)res
.str[0];
1773 } else if (res
.str.length
>= 2) {
1774 res
.val
= (cast(ubyte)res
.str[0])<<(ch
== '"' ?
0 : 8);
1775 res
.val |
= (cast(ubyte)res
.str[1])<<(ch
== '"' ?
8 : 0);
1780 EERROR(URAsmExprError
.Term
);
1788 if (pr
.empty || pr
.front
<= ' ' || pr
.eol
) EERROR(URAsmExprError
.Marg
);
1789 if (urGetValueFn
!is null) {
1790 urGetValueFn(ch
, pr
, res
, ei
.addr
);
1792 EERROR(URAsmExprError
.Marg
);
1797 auto lbl
= readLabelName(lblbuf
[], pr
);
1798 if (lbl
is null) EERROR(URAsmExprError
.Label
);
1800 if (!pr
.empty
&& pr
.front
== '(') {
1804 if (urCallFunctionFn
!is null) {
1805 urCallFunctionFn(lbl
, pr
, res
, ei
.addr
);
1807 if (!pr
.empty
&& pr
.front
== ')') { pr
.popFront(); break; }
1809 EERROR(URAsmExprError
.Func
);
1812 if (!ei
.logDone
) getAddr(lbl
, res
, ei
);
1819 const(ExprOperator
)* getOperator (int prio
, ref URAsmParser pr
, ref ExprInfo ei
) {
1820 if (pr
.empty
) return null;
1821 char opc
= pr
.front
;
1823 const(ExprOperator
)* res
= operators
.ptr
, cur
;
1824 for (cur
= res
, res
= null; cur
.prio
>= 0; ++cur
) {
1826 if (oplen
> 1) continue;
1827 if (opc
== cur
.sn
) res
= cur
;
1829 int l
= cast(int)cur
.ln
.length
;
1830 if (l
< oplen
) continue;
1832 foreach (immutable idx
; 0..l
) if (pr
.peek(idx
) != cur
.ln
[idx
]) { ok
= false; break; }
1833 if (ok
) { res
= cur
; oplen
= l
; }
1836 if (res
!is null && res
.prio
!= prio
) res
= null;
1837 if (res
) foreach (immutable _
; 0..oplen
) pr
.popFront(); // eat operator
1842 void checkNotStr (ref URExprValue res
, ref URExprValue o1
) {
1843 if ((res
.str !is null && res
.str.length
> 2) ||
(o1
.str !is null && o1
.str.length
> 2)) {
1846 EERROR(URAsmExprError
.Type
);
1851 void expressionDo (int prio
, ref URAsmParser pr
, ref URExprValue res
, ref ExprInfo ei
) {
1852 const(ExprOperator
)* op
;
1855 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1856 if (pr
.front
== ')' || pr
.front
== ']') return;
1857 if (prio
<= 0) { term(pr
, res
, ei
); return; }
1859 if (prio
== UnaryPriority
) {
1863 if ((op
= getOperator(prio
, pr
, ei
)) is null) break;
1864 expressionDo(prio
, pr
, res
, ei
);
1866 checkNotStr(res
, o1
);
1867 op
.doer(res
, o1
, ei
);
1869 res
.fixuptype
= URAsmFixup
.None
;
1870 res
.val
= ei
.logRes
;
1874 if (!wasIt
) expressionDo(prio
-1, pr
, res
, ei
);
1878 expressionDo(prio
-1, pr
, res
, ei
);
1880 bool old
= ei
.logDone
;
1883 if (pr
.empty || pr
.front
== ';' || pr
.front
== ':' || pr
.front
== ')' || pr
.front
== ']') break;
1884 if ((op
= getOperator(prio
, pr
, ei
)) is null) break;
1887 case LogAndPriority
: // &&
1888 if (!res
.val
) { ei
.logDone
= true; ei
.logRes
= 0; }
1890 case LogOrPriority
: // ||
1891 if (res
.val
) { ei
.logDone
= true; ei
.logRes
= (res
.val
!= 0); }
1896 expressionDo(prio
-1, pr
, o1
, ei
); // second operand
1898 checkNotStr(res
, o1
);
1899 op
.doer(res
, o1
, ei
);
1902 res
.fixuptype
= URAsmFixup
.None
;
1903 res
.val
= ei
.logRes
;
1910 void expression (ref URAsmParser pr
, ref URExprValue res
, ref ExprInfo ei
) {
1913 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1915 case '-': neg = true; pr
.popFront(); break;
1916 case '+': neg = false; pr
.popFront(); break;
1919 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1920 expressionDo(MaxPriority
, pr
, res
, ei
);
1921 if (neg) res
.val
= -(res
.val
);
1922 pr
.skipBlanks(); // for convenience
1926 public void urExpressionEx (ref URAsmParser pr
, ref URExprValue res
, ushort addr
) {
1929 if (pr
.empty
) EERROR(URAsmExprError
.Eos
);
1934 expression(pr
, res
, ei
);
1935 res
.defined
= ei
.defined
;
1939 public int urExpression (ref URAsmParser pr
, ushort addr
, out bool defined
, out URAsmFixup fixuptype
) {
1942 fixuptype
= URAsmFixup
.None
;
1943 urExpressionEx(pr
, res
, addr
);
1944 fixuptype
= res
.fixuptype
;
1945 defined
= res
.defined
;
1946 if (res
.str !is null && res
.str.length
> 2) EERROR(URAsmExprError
.Type
);
1951 // ////////////////////////////////////////////////////////////////////////// //
1961 // UROpType.MIX0 ; no displacement
1962 // UROpType.MIY0 ; no displacement
1966 // UROpType.R8: v is 8-bit register index; warning: v==1 may be UROpType.COND(3)
1967 // UROpType.COND: v is condition index (warning: v==3 may be UROpType.R8(1))
1981 // trailing blanks skipped
1982 void urNextOperand (ref URAsmParser pr
, out URAOperand op
, ushort addr
) {
1986 op
.fixuptype
= URAsmFixup
.None
;
1988 UROpType ot
= UROpType
.NONE
;
1990 if (pr
.front
== '(') {
1993 if (pr
.empty
) EERROR(URAsmExprError
.Mem
);
1995 if ((pr
.front
== 'C' || pr
.front
== 'c') && (pr
.ahead
<= ' ' || pr
.ahead
== ')')) {
1996 op
.type
= UROpType
.PORTC
;
1999 if (pr
.empty || pr
.front
!= ')') EERROR(URAsmExprError
.Mem
);
2005 if ((pr
.front
== 'H' || pr
.front
== 'h') && (pr
.ahead
== 'L' || pr
.ahead
== 'l')) ot
= UROpType
.MHL
;
2006 else if ((pr
.front
== 'D' || pr
.front
== 'd') && (pr
.ahead
== 'E' || pr
.ahead
== 'e')) ot
= UROpType
.MDE
;
2007 else if ((pr
.front
== 'B' || pr
.front
== 'b') && (pr
.ahead
== 'C' || pr
.ahead
== 'c')) ot
= UROpType
.MBC
;
2008 else if ((pr
.front
== 'S' || pr
.front
== 's') && (pr
.ahead
== 'P' || pr
.ahead
== 'p')) ot
= UROpType
.MSP
;
2009 else if ((pr
.front
== 'I' || pr
.front
== 'i') && (pr
.ahead
== 'X' || pr
.ahead
== 'x'|| pr
.ahead
== 'Y' || pr
.ahead
== 'y')) {
2011 ot
= (pr
.ahead
== 'X' || pr
.ahead
== 'x' ? UROpType
.MIX
: UROpType
.MIY
);
2015 if (pr
.empty
) EERROR(URAsmExprError
.Mem
);
2016 if (pr
.front
== '+' || pr
.front
== '-') {
2018 op
.v
= urExpression(pr
, addr
, op
.defined
, op
.fixuptype
);
2020 if (op
.v
< byte.min || op
.v
> byte.max
) EERROR(URAsmExprError
.Mem
);
2025 ot
= (ot
== UROpType
.MIX ? UROpType
.MIX0
: UROpType
.MIY0
);
2030 op
.v
= urExpression(pr
, addr
, op
.defined
, op
.fixuptype
);
2031 ot
= UROpType
.MEM16
;
2033 if (ot
== UROpType
.NONE
) EERROR(URAsmExprError
.Mem
);
2034 if (doPop
) { pr
.popFront(); pr
.popFront(); }
2036 //conwriteln("empty=", pr.empty);
2037 //conwriteln("front=", pr.front);
2038 if (pr
.empty || pr
.front
!= ')') EERROR(URAsmExprError
.Mem
);
2048 void doCheck (string tk
, UROpType type
, int vv
=0) {
2049 foreach (immutable idx
, char ch
; tk
[]) {
2050 char pc
= pr
.peek(cast(uint)idx
);
2051 if (pc
>= 'a' && pc
<= 'z') pc
-= 32;
2052 if (pc
!= ch
) return;
2055 tklen
= cast(uint)tk
.length
;
2059 doCheck("I", UROpType
.R8I
);
2060 doCheck("R", UROpType
.R8R
);
2062 doCheck("B", UROpType
.R8
, 0);
2063 doCheck("C", UROpType
.R8
, 1); //WARNING! this may be condition as well
2064 doCheck("D", UROpType
.R8
, 2);
2065 doCheck("E", UROpType
.R8
, 3);
2066 doCheck("H", UROpType
.R8
, 4);
2067 doCheck("L", UROpType
.R8
, 5);
2068 doCheck("A", UROpType
.R8
, 7);
2070 doCheck("Z", UROpType
.COND
, 1);
2071 //doCheck("C", UROpType.COND, 3);
2072 doCheck("P", UROpType
.COND
, 6);
2073 doCheck("M", UROpType
.COND
, 7);
2075 doCheck("NZ", UROpType
.COND
, 0);
2076 doCheck("NC", UROpType
.COND
, 2);
2077 doCheck("PO", UROpType
.COND
, 4);
2078 doCheck("PE", UROpType
.COND
, 5);
2080 doCheck("HL", UROpType
.R16HL
);
2081 doCheck("DE", UROpType
.R16DE
);
2082 doCheck("BC", UROpType
.R16BC
);
2083 doCheck("AF", UROpType
.R16AF
);
2084 doCheck("SP", UROpType
.R16SP
);
2085 doCheck("IX", UROpType
.R16IX
);
2086 doCheck("IY", UROpType
.R16IY
);
2087 doCheck("XH", UROpType
.R8XH
);
2088 doCheck("YH", UROpType
.R8YH
);
2089 doCheck("XL", UROpType
.R8XL
);
2090 doCheck("YL", UROpType
.R8YL
);
2092 doCheck("AF'", UROpType
.R16AFX
);
2093 doCheck("AFX", UROpType
.R16AFX
);
2094 doCheck("IXH", UROpType
.R8XH
);
2095 doCheck("IYH", UROpType
.R8YH
);
2096 doCheck("IXL", UROpType
.R8XL
);
2097 doCheck("IYL", UROpType
.R8YL
);
2099 if (ot
!= UROpType
.NONE
) {
2100 // got register or another reserved thing?
2101 char ch
= pr
.peek(tklen
);
2102 if (ch
== ';' || ch
== ':' || ch
== ',' || ch
<= ' ') {
2104 foreach (immutable _
; 0..tklen
) pr
.popFront();
2111 op
.v
= urExpression(pr
, addr
, op
.defined
, op
.fixuptype
);
2112 op
.type
= UROpType
.IMM16
;
2117 // ////////////////////////////////////////////////////////////////////////// //
2119 bool urIsValidOp (ref URAOperand op
, ushort addr
, int opt
) {
2120 if (opt
== UROpType
.NONE
) return (op
.type
== UROpType
.NONE
);
2121 if (op
.type
== UROpType
.NONE
) return false;
2122 final switch (opt
) {
2124 if (op
.type
!= UROpType
.IMM16
) return false;
2125 if (op
.v
< byte.min || op
.v
> ubyte.max
) return false;
2127 case UROpType
.IMM16
:
2128 if (op
.type
!= UROpType
.IMM16
) return false;
2129 if (op
.v
< short.min || op
.v
> ushort.max
) return false;
2131 case UROpType
.ADDR16
:
2132 if (op
.type
!= UROpType
.IMM16
) return false;
2133 if (op
.v
< short.min || op
.v
> ushort.max
) return false;
2135 case UROpType
.ADDR8
:
2136 if (op
.type
!= UROpType
.IMM16
) return false;
2137 if (op
.v
< short.min || op
.v
> ushort.max
) return false;
2139 int dist
= op
.v
-(addr
+2);
2140 if (dist
< byte.min || dist
> byte.max
) return false;
2143 case UROpType
.MEM16
:
2144 if (op
.type
!= UROpType
.MEM16
) return false;
2148 if (op
.type
== UROpType
.MHL
) { op
.v
= 6; return true; } // (HL) is ok here
2150 case UROpType
.R8NOM
:
2151 case UROpType
.R83NOM
:
2152 // fix "C" condition
2153 if (op
.type
== UROpType
.COND
&& op
.v
== 3) { op
.type
= UROpType
.R8
; op
.v
= 1; }
2154 if (op
.type
!= UROpType
.R8
) return false;
2156 case UROpType
.PORTC
:
2157 return (op
.type
== UROpType
.PORTC
);
2158 case UROpType
.PORTIMM
:
2159 if (op
.type
!= UROpType
.MEM16
) return false; // mem, 'cause (n)
2160 if (op
.defined
&& (op
.v
< ubyte.min || op
.v
> ubyte.max
)) return false;
2168 case UROpType
.R16AF
:
2169 case UROpType
.R16AFX
:
2170 case UROpType
.R16BC
:
2171 case UROpType
.R16DE
:
2172 case UROpType
.R16HL
:
2173 case UROpType
.R16IX
:
2174 case UROpType
.R16IY
:
2175 case UROpType
.R16SP
:
2182 return (op
.type
== opt
);
2184 return (op
.type
== UROpType
.R8
&& op
.v
== 7);
2186 if (op
.type
== UROpType
.R16BC
) { op
.v
= 0; return true; }
2187 if (op
.type
== UROpType
.R16DE
) { op
.v
= 1; return true; }
2188 if (op
.type
== UROpType
.R16HL
) { op
.v
= 2; return true; }
2189 if (op
.type
== UROpType
.R16SP
) { op
.v
= 3; return true; }
2192 if (op
.type
== UROpType
.R16BC
) { op
.v
= 0; return true; }
2193 if (op
.type
== UROpType
.R16DE
) { op
.v
= 1; return true; }
2194 if (op
.type
== UROpType
.R16HL
) { op
.v
= 2; return true; }
2195 if (op
.type
== UROpType
.R16AF
) { op
.v
= 3; return true; }
2198 if (op
.type
!= UROpType
.MIX
&& op
.type
!= UROpType
.MIX0
) return false;
2199 if (op
.defined
&& (op
.v
< byte.min || op
.v
> byte.max
)) return false;
2202 if (op
.type
!= UROpType
.MIY
&& op
.type
!= UROpType
.MIY0
) return false;
2203 if (op
.defined
&& (op
.v
< byte.min || op
.v
> byte.max
)) return false;
2205 case UROpType
.JRCOND
:
2206 // fix "C" condition
2207 if (op
.type
== UROpType
.R8
&& op
.v
== 1) { op
.type
= UROpType
.COND
; op
.v
= 3; }
2208 if (op
.type
!= UROpType
.COND
) return false;
2209 return (op
.v
>= 0 && op
.v
<= 3);
2211 // fix "C" condition
2212 if (op
.type
== UROpType
.R8
&& op
.v
== 1) { op
.type
= UROpType
.COND
; op
.v
= 3; }
2213 return (op
.type
== UROpType
.COND
);
2215 if (op
.type
!= UROpType
.IMM16
) return false;
2216 if (op
.v
< 0 || op
.v
> 7) return false;
2218 case UROpType
.RSTDEST
:
2219 if (op
.type
!= UROpType
.IMM16
) return false;
2220 if (op
.v
< 0 || op
.v
> 0x38 ||
(op
.v
&0x07) != 0) return false;
2223 if (op
.type
!= UROpType
.IMM16
) return false;
2224 if (op
.v
!= 0) return false;
2227 if (op
.type
!= UROpType
.IMM16
) return false;
2228 if (op
.v
!= 1) return false;
2231 if (op
.type
!= UROpType
.IMM16
) return false;
2232 if (op
.v
!= 2) return false;
2239 /// buffer to keep assembled code
2240 public struct URAsmBuf
{
2241 ubyte[] dest
; /// can be of any length, will grow
2242 URAsmFixup
[] dfixs
; /// fixups
2244 ubyte[] code
; /// result of `urAssembleOne()` call, always slice of `dest`
2245 URAsmFixup
[] fixup
; /// result of `urAssembleOne()` call, always slice of `dfixs`
2247 void reset () pure nothrow @safe @nogc { destused
= 0; code
= null; fixup
= null; }
2249 void putByte (ubyte v
, URAsmFixup fix
=URAsmFixup
.None
) pure nothrow @safe {
2250 if (destused
>= dest
.length
) dest
.length
+= 64; // way too much! ;-)
2251 if (destused
>= dfixs
.length
) dfixs
.length
+= 64; // way too much! ;-)
2253 dfixs
[destused
] = fix
;
2255 code
= dest
[0..destused
];
2256 fixup
= dfixs
[0..destused
];
2259 void putWord (ushort v
, URAsmFixup fix
=URAsmFixup
.None
) pure nothrow @safe {
2260 putByte(v
&0xff, fix
);
2261 putByte((v
>>8)&0xff, URAsmFixup
.None
);
2266 /// understands comments
2267 void urAssembleOne (ref URAsmBuf dbuf
, ref URAsmParser pr
, ushort addr
) {
2271 const(URAsmCmdInfo
)* cm
;
2275 void doOperand (int idx
, ref uint code
) {
2276 const(URAOperand
)* op
= ops
.ptr
+idx
;
2277 switch (cm
.ops
[idx
]) {
2279 case UROpType
.PORTIMM
:
2280 if (op
.fixuptype
!= URAsmFixup
.None
) {
2281 if (op
.fixuptype
== URAsmFixup
.Word
) throw new Exception("invalid fixup");
2283 dbuf
.putByte(op
.v
&0xFFU
, op
.fixuptype
);
2285 case UROpType
.ADDR8
:
2287 int dist
= op
.v
-(addr
+2);
2288 if (dist
< byte.min || dist
> byte.max
) throw new Exception("invalid jr destination");
2289 dbuf
.putByte(dist
&0xff);
2294 case UROpType
.IMM16
:
2295 case UROpType
.ADDR16
:
2296 case UROpType
.MEM16
:
2297 dbuf
.putWord(op
.v
&0xFFFFU
, op
.fixuptype
);
2300 case UROpType
.R8NOM
:
2303 case UROpType
.RSTDEST
:
2304 code |
= op
.v
&0b111000;
2306 case UROpType
.JRCOND
:
2310 case UROpType
.R83NOM
:
2311 code |
= (op
.v
&0xFFU
)<<3;
2315 code |
= (op
.v
&0xFFU
)<<4;
2319 dbuf
.putByte(cast(ubyte)op
.v
);
2325 void genCode (void) {
2326 cmdloop
: for (int pos
= cast(int)URInstructionsTable
.length
-1; pos
>= 0; --pos
) {
2327 if (tkn
!= URInstructionsTable
.ptr
[pos
].mnemo
) continue;
2328 foreach (immutable oprn
, ref op
; ops
[]) {
2329 if (!urIsValidOp(op
, addr
, URInstructionsTable
.ptr
[pos
].ops
.ptr
[oprn
])) continue cmdloop
;
2331 // command found, generate code
2332 cm
= URInstructionsTable
.ptr
+pos
;
2333 uint code
= cm
.code
;
2334 uint mask
= cm
.mask
;
2335 if ((code
&0xFFFFU
) == 0xCBDDU ||
(code
&0xFFFFU
) == 0xCBFDU
) {
2337 // emit unmasked code
2338 dbuf
.putByte(code
&0xFFU
);
2342 foreach (immutable oprn
; 0..3) {
2343 if (cm
.ops
[oprn
] == UROpType
.MIX || cm
.ops
[oprn
] == UROpType
.MIY
) {
2344 if (ops
[oprn
].defined
&& (ops
[oprn
].v
< byte.min || ops
[oprn
].v
> byte.max
)) throw new Exception("invalid displacement");
2345 if (ops
[oprn
].defined
) dbuf
.dest
[dbuf
.destused
-2] = cast(ubyte)ops
[oprn
].v
;
2349 auto ccpos
= dbuf
.destused
-1;
2353 if ((mask
&0xFFU
) != 0xFFU
) {
2354 foreach (immutable oprn
; 0..3) if (cm
.ops
[oprn
] != UROpType
.MIX
&& cm
.ops
[oprn
] != UROpType
.MIY
) doOperand(oprn
, code
);
2356 dbuf
.dest
[ccpos
] = cast(ubyte)code
;
2361 // emit unmasked code
2362 while ((mask
&0xFFU
) == 0xFFU
) {
2363 dbuf
.putByte(code
&0xFFU
);
2367 //ASSERT((code&0xFFFFFF00UL) == 0);
2370 code
= dbuf
.dest
[--dbuf
.destused
];
2372 uint ccpos
= dbuf
.destused
;
2377 dbuf
.dest
[ccpos
] = cast(ubyte)code
;
2382 throw new Exception("invalid instruction");
2390 if (first
) throw new Exception("invalid operand");
2392 } else if (!first
) {
2393 if (pr
.empty || pr
.front
!= ',') throw new Exception("invalid operand");
2396 if (pr
.eol
) throw new Exception("invalid operand");
2398 ops
[] = URAOperand
.init
;
2399 urNextOperand(pr
, ops
[0], addr
);
2405 void dorep (int opcnt
) {
2410 if (first
) throw new Exception("invalid operand");
2412 } else if (!first
) {
2413 if (pr
.empty || pr
.front
!= ',') throw new Exception("invalid operand");
2416 if (pr
.eol
) throw new Exception("invalid operand");
2418 ops
[] = URAOperand
.init
;
2419 foreach (immutable c
; 0..opcnt
) {
2422 if (pr
.empty || pr
.front
!= ',') throw new Exception("invalid operand");
2425 if (pr
.eol
) throw new Exception("invalid operand");
2427 urNextOperand(pr
, ops
[c
], addr
);
2429 // shifts has special (I?+n),r8 forms
2430 if (opcnt
== 1 && tkn
!= URMnemo
.INC
&& tkn
!= URMnemo
.DEC
) {
2431 if (ops
[0].type
== UROpType
.MIX || ops
[0].type
== UROpType
.MIY || ops
[0].type
== UROpType
.MIX0 || ops
[0].type
== UROpType
.MIY0
) {
2432 if (!first
) throw new Exception("invalid operand mix");
2434 if (!pr
.empty
&& pr
.front
== ',') urNextOperand(pr
, ops
[1], addr
);
2436 if (!pr
.eol
) throw new Exception("invalid operand");
2448 if (pr
.empty || pr
.front
== ';') return;
2449 if (URAsmParser
.isalpha(pr
.front
)) break;
2450 if (pr
.front
== ':') { pr
.popFront(); continue; }
2451 throw new Exception("invalid instruction");
2454 //if (expr[0] == ':') { if (errpos) *errpos = expr; return 0; }
2459 if (ch
>= 'a' && ch
<= 'z') ch
-= 32;
2460 if (ch
>= 'A' && ch
<= 'Z') {
2461 if (mmlen
> mnem
.length
) throw new Exception("invalid instruction");
2468 if (mmlen
== 0) throw new Exception("invalid instruction");
2469 if (!pr
.empty
&& pr
.front
> ' ' && pr
.front
!= ';' && pr
.front
!= ':') throw new Exception("invalid instruction");
2472 for (tkn
= 0; tkn
<= URMnemo
.max
; ++tkn
) if (mnem
[0..mmlen
] == URMnemonics
.ptr
[tkn
]) break;
2473 if (tkn
> URMnemo
.max
) throw new Exception("invalid instruction");
2476 // special for PUSH and POP
2483 // special for RR/RL
2499 foreach (immutable ci
, ref URAOperand op
; ops
[]) {
2503 if (pr
.empty || pr
.front
!= ',') throw new Exception("invalid operand");
2506 if (pr
.eol
) throw new Exception("invalid operand");
2508 urNextOperand(pr
, op
, addr
);
2509 //conwriteln("op #", ci, ": ", op.toString, " <", pr.text[pr.textpos..$], ">");
2513 if (!pr
.eol
) throw new Exception("invalid operand");
2519 // ////////////////////////////////////////////////////////////////////////// //
2520 version(urasm_test
) {
2525 void testOne (string xname
) {
2526 conwriteln("=== ", xname
, " ===");
2529 auto fi
= VFile("_urtests/"~xname
~"_0000.bin");
2530 eta
.length
= cast(uint)fi
.size
;
2531 fi
.rawReadExact(eta
[]);
2535 foreach (string s
; VFile("_urtests/"~xname
~".asm").byLineCopy
) {
2536 //conwritefln!"%04X: %s: %s"(addr, addr, s);
2538 auto pr
= URAsmParser(s
);
2539 urAssembleOne(abuf
, pr
, addr
);
2541 if (!pr
.empty
&& pr
.front
!= ';') assert(0, "extra text");
2542 foreach (immutable idx
, ubyte b
; abuf
.code
) {
2543 if (b
!= eta
[addr
+idx
]) {
2544 conwritefln
!"%04X: %02X %02X"(addr
+idx
, eta
[addr
+idx
], b
);
2545 assert(0, "fucked");
2549 addr
+= abuf
.code
.length
;
2551 //auto fo = VFile("zres.bin", "w");
2552 //fo.rawWriteExact(res);
2559 auto db = urAssembleOne(buf
[], "ex af,afx", 0);
2560 conwriteln("len=", db.length
);
2564 while (addr
< db.length
) {
2565 auto len
= urDisassembleOne(dis
, addr
, (ushort addr
) => buf
[addr
&0x0f]);
2566 conwriteln("dlen=", len
);
2567 conwriteln(" ", dis
.getbuf
);
2571 testOne("allb_smp");