egra: some cleanups in agg mini rasterizer
[iv.d.git] / olly / asm1.d
blob14b6f6c2c92839578633bdf7fbddfc538926f4af
1 // Free Disassembler and Assembler -- Header file
2 //
3 // Copyright (C) 2001 Oleh Yuschuk
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 module iv.olly.asm1 /*is aliced*/;
19 import iv.alice;
21 /// symbol resolver; should throw on unknown symbol
22 alias uint delegate (const(char)[] name) ResolveSymCB;
24 /// "db" and company will call this; no cb means limited support; size: element size in data buffer
25 alias void delegate (uint addr, ubyte b) PutDataCB;
27 /// Model to search for assembler command
28 public struct AsmModel {
29 ubyte[ASMMAXCMDSIZE] code; /// Binary code
30 ubyte[ASMMAXCMDSIZE] mask; /// Mask for binary code (0: bit ignored)
31 int length; /// Length of code, bytes (0: empty)
32 int jmpsize; /// Offset size if relative jump
33 int jmpoffset; /// Offset relative to IP
34 int jmppos; /// Position of jump offset in command
35 bool data; /// db, etc
38 /// Assembler options
39 public struct AsmOptions {
40 bool ideal = true; /// Force IDEAL decoding mode
41 bool sizesens = true; /// How to encode size-sensitive mnemonics (false: word, true: dword)
42 bool defaultHex = false; /// default number base is hex
46 // ////////////////////////////////////////////////////////////////////////// //
47 private:
49 enum PSEUDOOP = 128; // Base for pseudooperands
50 enum TEXTLEN = 256; // Maximal length of text string
52 // Special command features.
53 enum {
54 WW = 0x01, // Bit W (size of operand)
55 SS = 0x02, // Bit S (sign extention of immediate)
56 WS = 0x03, // Bits W and S
57 W3 = 0x08, // Bit W at position 3
58 CC = 0x10, // Conditional jump
59 FF = 0x20, // Forced 16-bit size
60 LL = 0x40, // Conditional loop
61 PR = 0x80, // Protected command
62 WP = 0x81, // I/O command with bit W
65 // All possible types of operands in 80x86. A bit more than you expected, he?
66 enum {
67 NNN, // No operand
68 REG, // Integer register in Reg field
69 RCM, // Integer register in command byte
70 RG4, // Integer 4-byte register in Reg field
71 RAC, // Accumulator (AL/AX/EAX, implicit)
72 RAX, // AX (2-byte, implicit)
73 RDX, // DX (16-bit implicit port address)
74 RCL, // Implicit CL register (for shifts)
75 RS0, // Top of FPU stack (ST(0), implicit)
76 RST, // FPU register (ST(i)) in command byte
77 RMX, // MMX register MMx
78 R3D, // 3DNow! register MMx
79 MRG, // Memory/register in ModRM byte
80 MR1, // 1-byte memory/register in ModRM byte
81 MR2, // 2-byte memory/register in ModRM byte
82 MR4, // 4-byte memory/register in ModRM byte
83 RR4, // 4-byte memory/register (register only)
84 MR8, // 8-byte memory/MMX register in ModRM
85 RR8, // 8-byte MMX register only in ModRM
86 MRD, // 8-byte memory/3DNow! register in ModRM
87 RRD, // 8-byte memory/3DNow! (register only)
88 MRJ, // Memory/reg in ModRM as JUMP target
89 MMA, // Memory address in ModRM byte for LEA
90 MML, // Memory in ModRM byte (for LES)
91 MMS, // Memory in ModRM byte (as SEG:OFFS)
92 MM6, // Memory in ModRm (6-byte descriptor)
93 MMB, // Two adjacent memory locations (BOUND)
94 MD2, // Memory in ModRM (16-bit integer)
95 MB2, // Memory in ModRM (16-bit binary)
96 MD4, // Memory in ModRM byte (32-bit integer)
97 MD8, // Memory in ModRM byte (64-bit integer)
98 MDA, // Memory in ModRM byte (80-bit BCD)
99 MF4, // Memory in ModRM byte (32-bit float)
100 MF8, // Memory in ModRM byte (64-bit float)
101 MFA, // Memory in ModRM byte (80-bit float)
102 MFE, // Memory in ModRM byte (FPU environment)
103 MFS, // Memory in ModRM byte (FPU state)
104 MFX, // Memory in ModRM byte (ext. FPU state)
105 MSO, // Source in string op's ([ESI])
106 MDE, // Destination in string op's ([EDI])
107 MXL, // XLAT operand ([EBX+AL])
108 IMM, // Immediate data (8 or 16/32)
109 IMU, // Immediate unsigned data (8 or 16/32)
110 VXD, // VxD service
111 IMX, // Immediate sign-extendable byte
112 C01, // Implicit constant 1 (for shifts)
113 IMS, // Immediate byte (for shifts)
114 IM1, // Immediate byte
115 IM2, // Immediate word (ENTER/RET)
116 IMA, // Immediate absolute near data address
117 JOB, // Immediate byte offset (for jumps)
118 JOW, // Immediate full offset (for jumps)
119 JMF, // Immediate absolute far jump/call addr
120 SGM, // Segment register in ModRM byte
121 SCM, // Segment register in command byte
122 CRX, // Control register CRx
123 DRX, // Debug register DRx
126 // Pseudooperands (implicit operands, never appear in assembler commands). Must
127 // have index equal to or exceeding PSEUDOOP.
128 enum {
129 PRN = PSEUDOOP, // Near return address
130 PRF, // Far return address
131 PAC, // Accumulator (AL/AX/EAX)
132 PAH, // AH (in LAHF/SAHF commands)
133 PFL, // Lower byte of flags (in LAHF/SAHF)
134 PS0, // Top of FPU stack (ST(0))
135 PS1, // ST(1)
136 PCX, // CX/ECX
137 PDI, // EDI (in MMX extentions)
140 struct AsmInstrData {
141 uint mask; // Mask for first 4 bytes of the command
142 uint code; // Compare masked bytes with this
143 ubyte len; // Length of the main command code
144 ubyte bits; // Special bits within the command
145 ubyte arg1, arg2, arg3; // Types of possible arguments
146 ubyte type; // C_xxx + additional information
147 string name; // Symbolic name for this command
151 // ////////////////////////////////////////////////////////////////////////// //
152 // ///////////////// ASSEMBLER, DISASSEMBLER AND EXPRESSIONS //////////////// //
153 public enum ASMMAXCMDSIZE = 16; // Maximal length of 80x86 command
154 public enum ASMMAXCALSIZE = 8; // Max length of CALL without prefixes
155 public enum ASMNMODELS = 8; // Number of assembler search models
157 // Indexes of general-purpose registers in t_reg.
158 enum {
159 REG_EAX,
160 REG_ECX,
161 REG_EDX,
162 REG_EBX,
163 REG_ESP,
164 REG_EBP,
165 REG_ESI,
166 REG_EDI,
169 // Indexes of segment/selector registers
170 enum {
171 SEG_UNDEF = -1,
172 SEG_ES,
173 SEG_CS,
174 SEG_SS,
175 SEG_DS,
176 SEG_FS,
177 SEG_GS,
180 enum C_TYPEMASK = 0xF0; // Mask for command type
181 enum C_CMD = 0x00; // Ordinary instruction
182 enum C_PSH = 0x10; // 1-word PUSH instruction
183 enum C_POP = 0x20; // 1-word POP instruction
184 enum C_MMX = 0x30; // MMX instruction
185 enum C_FLT = 0x40; // FPU instruction
186 enum C_JMP = 0x50; // JUMP instruction
187 enum C_JMC = 0x60; // Conditional JUMP instruction
188 enum C_CAL = 0x70; // CALL instruction
189 enum C_RET = 0x80; // RET instruction
190 enum C_FLG = 0x90; // Changes system flags
191 enum C_RTF = 0xA0; // C_JMP and C_FLG simultaneously
192 enum C_REP = 0xB0; // Instruction with REPxx prefix
193 enum C_PRI = 0xC0; // Privileged instruction
194 enum C_DAT = 0xD0; // Data (address) doubleword
195 enum C_NOW = 0xE0; // 3DNow! instruction
196 enum C_BAD = 0xF0; // Unrecognized command
197 enum C_RARE = 0x08; // Rare command, seldom used in programs
198 enum C_SIZEMASK = 0x07; // MMX data size or special flag
199 enum C_EXPL = 0x01; // (non-MMX) Specify explicit memory size
201 // ////////////////////////////////////////////////////////////////////////// //
202 // Initialized constant data structures used by all programs from assembler
203 // package. Contain names of register, register combinations or commands and
204 // their properties.
206 static immutable string[9][3] regname = [
207 ["AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8" ],
208 ["AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R16"],
209 ["EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI","R32"],
212 static immutable string[8] segname = ["ES","CS","SS","DS","FS","GS","SEG?","SEG?"];
214 static immutable string[11] sizename = [
215 "(0-BYTE)", "BYTE", "WORD", "(3-BYTE)",
216 "DWORD", "(5-BYTE)", "FWORD", "(7-BYTE)",
217 "QWORD", "(9-BYTE)", "TBYTE"
220 static immutable int[8] addr32 = [
221 SEG_DS,
222 SEG_DS,
223 SEG_DS,
224 SEG_DS,
225 SEG_SS,
226 SEG_SS,
227 SEG_DS,
228 SEG_DS,
231 static immutable string[9] fpuname = ["ST0","ST1","ST2","ST3","ST4","ST5","ST6","ST7","FPU"];
232 static immutable string[9] mmxname = ["MM0","MM1","MM2","MM3","MM4","MM5","MM6","MM7","MMX"];
233 static immutable string[9] crname = ["CR0","CR1","CR2","CR3","CR4","CR5","CR6","CR7","CRX"];
234 static immutable string[9] drname = ["DR0","DR1","DR2","DR3","DR4","DR5","DR6","DR7","DRX"];
236 private __gshared uint[140][26] asmmnemolist; // 26 latin letters
238 shared static this () {
239 foreach (ref arr; asmmnemolist) arr[] = uint.max;
240 foreach (immutable idx, const ref ai; asmInstrs) {
241 auto np = ai.name.ptr;
242 while (*np && (*np < 'A' || *np > 'Z')) ++np;
243 if (*np < 'A' || *np > 'Z') assert(0, "invalid asm mnemonic: "~ai.name);
244 bool ok = false;
245 foreach (immutable xidx, ref uint ni; asmmnemolist[*np-'A']) {
246 if (ni == uint.max && xidx < asmmnemolist[*np-'A'].length-1) {
247 ok = true;
248 ni = cast(uint)idx;
249 break;
252 if (!ok) assert(0, "too many commands starting with letter '"~(*np)~"'");
256 // List of available processor commands with decoding, types of parameters and
257 // other useful information. Last element has field mask=0. If mnemonic begins
258 // with ampersand ('&'), its mnemonic decodes differently depending on operand
259 // size (16 or 32 bits). If mnemonic begins with dollar ('$'), this mnemonic
260 // depends on address size. Semicolon (':') separates 16-bit form from 32-bit,
261 // asterisk ('*') will be substituted by either W (16), D (32) or none (16/32)
262 // character. If command is of type C_MMX or C_NOW, or if type contains C_EXPL
263 // (=0x01), Disassembler must specify explicit size of memory operand.
264 static immutable AsmInstrData[585] asmInstrs = [
265 AsmInstrData(0x0000FF, 0x000090, 1,00, NNN,NNN,NNN, C_CMD+0, "NOP\0"),
266 AsmInstrData(0x0000FE, 0x00008A, 1,WW, REG,MRG,NNN, C_CMD+0, "MOV\0"),
267 AsmInstrData(0x0000F8, 0x000050, 1,00, RCM,NNN,NNN, C_PSH+0, "PUSH\0"),
268 AsmInstrData(0x0000FE, 0x000088, 1,WW, MRG,REG,NNN, C_CMD+0, "MOV\0"),
269 AsmInstrData(0x0000FF, 0x0000E8, 1,00, JOW,NNN,NNN, C_CAL+0, "CALL\0"),
270 AsmInstrData(0x0000FD, 0x000068, 1,SS, IMM,NNN,NNN, C_PSH+0, "PUSH\0"),
271 AsmInstrData(0x0000FF, 0x00008D, 1,00, REG,MMA,NNN, C_CMD+0, "LEA\0"),
272 AsmInstrData(0x0000FF, 0x000074, 1,CC, JOB,NNN,NNN, C_JMC+0, "JE,JZ\0"),
273 AsmInstrData(0x0000F8, 0x000058, 1,00, RCM,NNN,NNN, C_POP+0, "POP\0"),
274 AsmInstrData(0x0038FC, 0x000080, 1,WS, MRG,IMM,NNN, C_CMD+1, "ADD\0"),
275 AsmInstrData(0x0000FF, 0x000075, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNZ,JNE\0"),
276 AsmInstrData(0x0000FF, 0x0000EB, 1,00, JOB,NNN,NNN, C_JMP+0, "JMP\0"),
277 AsmInstrData(0x0000FF, 0x0000E9, 1,00, JOW,NNN,NNN, C_JMP+0, "JMP\0"),
278 AsmInstrData(0x0000FE, 0x000084, 1,WW, MRG,REG,NNN, C_CMD+0, "TEST\0"),
279 AsmInstrData(0x0038FE, 0x0000C6, 1,WW, MRG,IMM,NNN, C_CMD+1, "MOV\0"),
280 AsmInstrData(0x0000FE, 0x000032, 1,WW, REG,MRG,NNN, C_CMD+0, "XOR\0"),
281 AsmInstrData(0x0000FE, 0x00003A, 1,WW, REG,MRG,NNN, C_CMD+0, "CMP\0"),
282 AsmInstrData(0x0038FC, 0x003880, 1,WS, MRG,IMM,NNN, C_CMD+1, "CMP\0"),
283 AsmInstrData(0x0038FF, 0x0010FF, 1,00, MRJ,NNN,NNN, C_CAL+0, "CALL\0"),
284 AsmInstrData(0x0000FF, 0x0000C3, 1,00, PRN,NNN,NNN, C_RET+0, "RETN,RET\0"),
285 AsmInstrData(0x0000F0, 0x0000B0, 1,W3, RCM,IMM,NNN, C_CMD+0, "MOV\0"),
286 AsmInstrData(0x0000FE, 0x0000A0, 1,WW, RAC,IMA,NNN, C_CMD+0, "MOV\0"),
287 AsmInstrData(0x00FFFF, 0x00840F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JE,JZ\0"),
288 AsmInstrData(0x0000F8, 0x000040, 1,00, RCM,NNN,NNN, C_CMD+0, "INC\0"),
289 AsmInstrData(0x0038FE, 0x0000F6, 1,WW, MRG,IMU,NNN, C_CMD+1, "TEST\0"),
290 AsmInstrData(0x0000FE, 0x0000A2, 1,WW, IMA,RAC,NNN, C_CMD+0, "MOV\0"),
291 AsmInstrData(0x0000FE, 0x00002A, 1,WW, REG,MRG,NNN, C_CMD+0, "SUB\0"),
292 AsmInstrData(0x0000FF, 0x00007E, 1,CC, JOB,NNN,NNN, C_JMC+0, "JLE,JNG\0"),
293 AsmInstrData(0x00FFFF, 0x00850F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNZ,JNE\0"),
294 AsmInstrData(0x0000FF, 0x0000C2, 1,00, IM2,PRN,NNN, C_RET+0, "RETN\0"),
295 AsmInstrData(0x0038FF, 0x0030FF, 1,00, MRG,NNN,NNN, C_PSH+1, "PUSH\0"),
296 AsmInstrData(0x0038FC, 0x000880, 1,WS, MRG,IMU,NNN, C_CMD+1, "OR\0"),
297 AsmInstrData(0x0038FC, 0x002880, 1,WS, MRG,IMM,NNN, C_CMD+1, "SUB\0"),
298 AsmInstrData(0x0000F8, 0x000048, 1,00, RCM,NNN,NNN, C_CMD+0, "DEC\0"),
299 AsmInstrData(0x00FFFF, 0x00BF0F, 2,00, REG,MR2,NNN, C_CMD+1, "MOVSX\0"),
300 AsmInstrData(0x0000FF, 0x00007C, 1,CC, JOB,NNN,NNN, C_JMC+0, "JL,JNGE\0"),
301 AsmInstrData(0x0000FE, 0x000002, 1,WW, REG,MRG,NNN, C_CMD+0, "ADD\0"),
302 AsmInstrData(0x0038FC, 0x002080, 1,WS, MRG,IMU,NNN, C_CMD+1, "AND\0"),
303 AsmInstrData(0x0000FE, 0x00003C, 1,WW, RAC,IMM,NNN, C_CMD+0, "CMP\0"),
304 AsmInstrData(0x0038FF, 0x0020FF, 1,00, MRJ,NNN,NNN, C_JMP+0, "JMP\0"),
305 AsmInstrData(0x0038FE, 0x0010F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "NOT\0"),
306 AsmInstrData(0x0038FE, 0x0028C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SHR\0"),
307 AsmInstrData(0x0000FE, 0x000038, 1,WW, MRG,REG,NNN, C_CMD+0, "CMP\0"),
308 AsmInstrData(0x0000FF, 0x00007D, 1,CC, JOB,NNN,NNN, C_JMC+0, "JGE,JNL\0"),
309 AsmInstrData(0x0000FF, 0x00007F, 1,CC, JOB,NNN,NNN, C_JMC+0, "JG,JNLE\0"),
310 AsmInstrData(0x0038FE, 0x0020C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SHL\0"),
311 AsmInstrData(0x0000FE, 0x00001A, 1,WW, REG,MRG,NNN, C_CMD+0, "SBB\0"),
312 AsmInstrData(0x0038FE, 0x0018F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "NEG\0"),
313 AsmInstrData(0x0000FF, 0x0000C9, 1,00, NNN,NNN,NNN, C_CMD+0, "LEAVE\0"),
314 AsmInstrData(0x0000FF, 0x000060, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "&PUSHA*\0"),
315 AsmInstrData(0x0038FF, 0x00008F, 1,00, MRG,NNN,NNN, C_POP+1, "POP\0"),
316 AsmInstrData(0x0000FF, 0x000061, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "&POPA*\0"),
317 AsmInstrData(0x0000F8, 0x000090, 1,00, RAC,RCM,NNN, C_CMD+0, "XCHG\0"),
318 AsmInstrData(0x0000FE, 0x000086, 1,WW, MRG,REG,NNN, C_CMD+0, "XCHG\0"),
319 AsmInstrData(0x0000FE, 0x000000, 1,WW, MRG,REG,NNN, C_CMD+0, "ADD\0"),
320 AsmInstrData(0x0000FE, 0x000010, 1,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "ADC\0"),
321 AsmInstrData(0x0000FE, 0x000012, 1,WW, REG,MRG,NNN, C_CMD+C_RARE+0, "ADC\0"),
322 AsmInstrData(0x0000FE, 0x000020, 1,WW, MRG,REG,NNN, C_CMD+0, "AND\0"),
323 AsmInstrData(0x0000FE, 0x000022, 1,WW, REG,MRG,NNN, C_CMD+0, "AND\0"),
324 AsmInstrData(0x0000FE, 0x000008, 1,WW, MRG,REG,NNN, C_CMD+0, "OR\0"),
325 AsmInstrData(0x0000FE, 0x00000A, 1,WW, REG,MRG,NNN, C_CMD+0, "OR\0"),
326 AsmInstrData(0x0000FE, 0x000028, 1,WW, MRG,REG,NNN, C_CMD+0, "SUB\0"),
327 AsmInstrData(0x0000FE, 0x000018, 1,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "SBB\0"),
328 AsmInstrData(0x0000FE, 0x000030, 1,WW, MRG,REG,NNN, C_CMD+0, "XOR\0"),
329 AsmInstrData(0x0038FC, 0x001080, 1,WS, MRG,IMM,NNN, C_CMD+C_RARE+1, "ADC\0"),
330 AsmInstrData(0x0038FC, 0x001880, 1,WS, MRG,IMM,NNN, C_CMD+C_RARE+1, "SBB\0"),
331 AsmInstrData(0x0038FC, 0x003080, 1,WS, MRG,IMU,NNN, C_CMD+1, "XOR\0"),
332 AsmInstrData(0x0000FE, 0x000004, 1,WW, RAC,IMM,NNN, C_CMD+0, "ADD\0"),
333 AsmInstrData(0x0000FE, 0x000014, 1,WW, RAC,IMM,NNN, C_CMD+C_RARE+0, "ADC\0"),
334 AsmInstrData(0x0000FE, 0x000024, 1,WW, RAC,IMU,NNN, C_CMD+0, "AND\0"),
335 AsmInstrData(0x0000FE, 0x00000C, 1,WW, RAC,IMU,NNN, C_CMD+0, "OR\0"),
336 AsmInstrData(0x0000FE, 0x00002C, 1,WW, RAC,IMM,NNN, C_CMD+0, "SUB\0"),
337 AsmInstrData(0x0000FE, 0x00001C, 1,WW, RAC,IMM,NNN, C_CMD+C_RARE+0, "SBB\0"),
338 AsmInstrData(0x0000FE, 0x000034, 1,WW, RAC,IMU,NNN, C_CMD+0, "XOR\0"),
339 AsmInstrData(0x0038FE, 0x0000FE, 1,WW, MRG,NNN,NNN, C_CMD+1, "INC\0"),
340 AsmInstrData(0x0038FE, 0x0008FE, 1,WW, MRG,NNN,NNN, C_CMD+1, "DEC\0"),
341 AsmInstrData(0x0000FE, 0x0000A8, 1,WW, RAC,IMU,NNN, C_CMD+0, "TEST\0"),
342 AsmInstrData(0x0038FE, 0x0020F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "MUL\0"),
343 AsmInstrData(0x0038FE, 0x0028F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "IMUL\0"),
344 AsmInstrData(0x00FFFF, 0x00AF0F, 2,00, REG,MRG,NNN, C_CMD+0, "IMUL\0"),
345 AsmInstrData(0x0000FF, 0x00006B, 1,00, REG,MRG,IMX, C_CMD+C_RARE+0, "IMUL\0"),
346 AsmInstrData(0x0000FF, 0x000069, 1,00, REG,MRG,IMM, C_CMD+C_RARE+0, "IMUL\0"),
347 AsmInstrData(0x0038FE, 0x0030F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "DIV\0"),
348 AsmInstrData(0x0038FE, 0x0038F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "IDIV\0"),
349 AsmInstrData(0x0000FF, 0x000098, 1,00, NNN,NNN,NNN, C_CMD+0, "&CBW:CWDE\0"),
350 AsmInstrData(0x0000FF, 0x000099, 1,00, NNN,NNN,NNN, C_CMD+0, "&CWD:CDQ\0"),
351 AsmInstrData(0x0038FE, 0x0000D0, 1,WW, MRG,C01,NNN, C_CMD+1, "ROL\0"),
352 AsmInstrData(0x0038FE, 0x0008D0, 1,WW, MRG,C01,NNN, C_CMD+1, "ROR\0"),
353 AsmInstrData(0x0038FE, 0x0010D0, 1,WW, MRG,C01,NNN, C_CMD+1, "RCL\0"),
354 AsmInstrData(0x0038FE, 0x0018D0, 1,WW, MRG,C01,NNN, C_CMD+1, "RCR\0"),
355 AsmInstrData(0x0038FE, 0x0020D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SHL\0"),
356 AsmInstrData(0x0038FE, 0x0028D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SHR\0"),
357 AsmInstrData(0x0038FE, 0x0038D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SAR\0"),
358 AsmInstrData(0x0038FE, 0x0000D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "ROL\0"),
359 AsmInstrData(0x0038FE, 0x0008D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "ROR\0"),
360 AsmInstrData(0x0038FE, 0x0010D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "RCL\0"),
361 AsmInstrData(0x0038FE, 0x0018D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "RCR\0"),
362 AsmInstrData(0x0038FE, 0x0020D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SHL\0"),
363 AsmInstrData(0x0038FE, 0x0028D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SHR\0"),
364 AsmInstrData(0x0038FE, 0x0038D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SAR\0"),
365 AsmInstrData(0x0038FE, 0x0000C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "ROL\0"),
366 AsmInstrData(0x0038FE, 0x0008C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "ROR\0"),
367 AsmInstrData(0x0038FE, 0x0010C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "RCL\0"),
368 AsmInstrData(0x0038FE, 0x0018C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "RCR\0"),
369 AsmInstrData(0x0038FE, 0x0038C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SAR\0"),
370 AsmInstrData(0x0000FF, 0x000070, 1,CC, JOB,NNN,NNN, C_JMC+0, "JO\0"),
371 AsmInstrData(0x0000FF, 0x000071, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNO\0"),
372 AsmInstrData(0x0000FF, 0x000072, 1,CC, JOB,NNN,NNN, C_JMC+0, "JB,JC\0"),
373 AsmInstrData(0x0000FF, 0x000073, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNB,JNC\0"),
374 AsmInstrData(0x0000FF, 0x000076, 1,CC, JOB,NNN,NNN, C_JMC+0, "JBE,JNA\0"),
375 AsmInstrData(0x0000FF, 0x000077, 1,CC, JOB,NNN,NNN, C_JMC+0, "JA,JNBE\0"),
376 AsmInstrData(0x0000FF, 0x000078, 1,CC, JOB,NNN,NNN, C_JMC+0, "JS\0"),
377 AsmInstrData(0x0000FF, 0x000079, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNS\0"),
378 AsmInstrData(0x0000FF, 0x00007A, 1,CC, JOB,NNN,NNN, C_JMC+C_RARE+0, "JPE,JP\0"),
379 AsmInstrData(0x0000FF, 0x00007B, 1,CC, JOB,NNN,NNN, C_JMC+C_RARE+0, "JPO,JNP\0"),
380 AsmInstrData(0x0000FF, 0x0000E3, 1,00, JOB,NNN,NNN, C_JMC+C_RARE+0, "$JCXZ:JECXZ\0"),
381 AsmInstrData(0x00FFFF, 0x00800F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JO\0"),
382 AsmInstrData(0x00FFFF, 0x00810F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNO\0"),
383 AsmInstrData(0x00FFFF, 0x00820F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JB,JC\0"),
384 AsmInstrData(0x00FFFF, 0x00830F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNB,JNC\0"),
385 AsmInstrData(0x00FFFF, 0x00860F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JBE,JNA\0"),
386 AsmInstrData(0x00FFFF, 0x00870F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JA,JNBE\0"),
387 AsmInstrData(0x00FFFF, 0x00880F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JS\0"),
388 AsmInstrData(0x00FFFF, 0x00890F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNS\0"),
389 AsmInstrData(0x00FFFF, 0x008A0F, 2,CC, JOW,NNN,NNN, C_JMC+C_RARE+0, "JPE,JP\0"),
390 AsmInstrData(0x00FFFF, 0x008B0F, 2,CC, JOW,NNN,NNN, C_JMC+C_RARE+0, "JPO,JNP\0"),
391 AsmInstrData(0x00FFFF, 0x008C0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JL,JNGE\0"),
392 AsmInstrData(0x00FFFF, 0x008D0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JGE,JNL\0"),
393 AsmInstrData(0x00FFFF, 0x008E0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JLE,JNG\0"),
394 AsmInstrData(0x00FFFF, 0x008F0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JG,JNLE\0"),
395 AsmInstrData(0x0000FF, 0x0000F8, 1,00, NNN,NNN,NNN, C_CMD+0, "CLC\0"),
396 AsmInstrData(0x0000FF, 0x0000F9, 1,00, NNN,NNN,NNN, C_CMD+0, "STC\0"),
397 AsmInstrData(0x0000FF, 0x0000F5, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "CMC\0"),
398 AsmInstrData(0x0000FF, 0x0000FC, 1,00, NNN,NNN,NNN, C_CMD+0, "CLD\0"),
399 AsmInstrData(0x0000FF, 0x0000FD, 1,00, NNN,NNN,NNN, C_CMD+0, "STD\0"),
400 AsmInstrData(0x0000FF, 0x0000FA, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "CLI\0"),
401 AsmInstrData(0x0000FF, 0x0000FB, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "STI\0"),
402 AsmInstrData(0x0000FF, 0x00008C, 1,FF, MRG,SGM,NNN, C_CMD+C_RARE+0, "MOV\0"),
403 AsmInstrData(0x0000FF, 0x00008E, 1,FF, SGM,MRG,NNN, C_CMD+C_RARE+0, "MOV\0"),
404 AsmInstrData(0x0000FE, 0x0000A6, 1,WW, MSO,MDE,NNN, C_CMD+1, "CMPS\0"),
405 AsmInstrData(0x0000FE, 0x0000AC, 1,WW, MSO,NNN,NNN, C_CMD+1, "LODS\0"),
406 AsmInstrData(0x0000FE, 0x0000A4, 1,WW, MDE,MSO,NNN, C_CMD+1, "MOVS\0"),
407 AsmInstrData(0x0000FE, 0x0000AE, 1,WW, MDE,PAC,NNN, C_CMD+1, "SCAS\0"),
408 AsmInstrData(0x0000FE, 0x0000AA, 1,WW, MDE,PAC,NNN, C_CMD+1, "STOS\0"),
409 AsmInstrData(0x00FEFF, 0x00A4F3, 1,WW, MDE,MSO,PCX, C_REP+1, "REP MOVS\0"),
410 AsmInstrData(0x00FEFF, 0x00ACF3, 1,WW, MSO,PAC,PCX, C_REP+C_RARE+1, "REP LODS\0"),
411 AsmInstrData(0x00FEFF, 0x00AAF3, 1,WW, MDE,PAC,PCX, C_REP+1, "REP STOS\0"),
412 AsmInstrData(0x00FEFF, 0x00A6F3, 1,WW, MDE,MSO,PCX, C_REP+1, "REPE CMPS\0"),
413 AsmInstrData(0x00FEFF, 0x00AEF3, 1,WW, MDE,PAC,PCX, C_REP+1, "REPE SCAS\0"),
414 AsmInstrData(0x00FEFF, 0x00A6F2, 1,WW, MDE,MSO,PCX, C_REP+1, "REPNE CMPS\0"),
415 AsmInstrData(0x00FEFF, 0x00AEF2, 1,WW, MDE,PAC,PCX, C_REP+1, "REPNE SCAS\0"),
416 AsmInstrData(0x0000FF, 0x0000EA, 1,00, JMF,NNN,NNN, C_JMP+C_RARE+0, "JMP\0"),
417 AsmInstrData(0x0038FF, 0x0028FF, 1,00, MMS,NNN,NNN, C_JMP+C_RARE+1, "JMP\0"),
418 AsmInstrData(0x0000FF, 0x00009A, 1,00, JMF,NNN,NNN, C_CAL+C_RARE+0, "CALL\0"),
419 AsmInstrData(0x0038FF, 0x0018FF, 1,00, MMS,NNN,NNN, C_CAL+C_RARE+1, "CALL\0"),
420 AsmInstrData(0x0000FF, 0x0000CB, 1,00, PRF,NNN,NNN, C_RET+C_RARE+0, "RETF\0"),
421 AsmInstrData(0x0000FF, 0x0000CA, 1,00, IM2,PRF,NNN, C_RET+C_RARE+0, "RETF\0"),
422 AsmInstrData(0x00FFFF, 0x00A40F, 2,00, MRG,REG,IMS, C_CMD+0, "SHLD\0"),
423 AsmInstrData(0x00FFFF, 0x00AC0F, 2,00, MRG,REG,IMS, C_CMD+0, "SHRD\0"),
424 AsmInstrData(0x00FFFF, 0x00A50F, 2,00, MRG,REG,RCL, C_CMD+0, "SHLD\0"),
425 AsmInstrData(0x00FFFF, 0x00AD0F, 2,00, MRG,REG,RCL, C_CMD+0, "SHRD\0"),
426 AsmInstrData(0x00F8FF, 0x00C80F, 2,00, RCM,NNN,NNN, C_CMD+C_RARE+0, "BSWAP\0"),
427 AsmInstrData(0x00FEFF, 0x00C00F, 2,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "XADD\0"),
428 AsmInstrData(0x0000FF, 0x0000E2, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*\0"),
429 AsmInstrData(0x0000FF, 0x0000E1, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*E\0"),
430 AsmInstrData(0x0000FF, 0x0000E0, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*NE\0"),
431 AsmInstrData(0x0000FF, 0x0000C8, 1,00, IM2,IM1,NNN, C_CMD+0, "ENTER\0"),
432 AsmInstrData(0x0000FE, 0x0000E4, 1,WP, RAC,IM1,NNN, C_CMD+C_RARE+0, "IN\0"),
433 AsmInstrData(0x0000FE, 0x0000EC, 1,WP, RAC,RDX,NNN, C_CMD+C_RARE+0, "IN\0"),
434 AsmInstrData(0x0000FE, 0x0000E6, 1,WP, IM1,RAC,NNN, C_CMD+C_RARE+0, "OUT\0"),
435 AsmInstrData(0x0000FE, 0x0000EE, 1,WP, RDX,RAC,NNN, C_CMD+C_RARE+0, "OUT\0"),
436 AsmInstrData(0x0000FE, 0x00006C, 1,WP, MDE,RDX,NNN, C_CMD+C_RARE+1, "INS\0"),
437 AsmInstrData(0x0000FE, 0x00006E, 1,WP, RDX,MDE,NNN, C_CMD+C_RARE+1, "OUTS\0"),
438 AsmInstrData(0x00FEFF, 0x006CF3, 1,WP, MDE,RDX,PCX, C_REP+C_RARE+1, "REP INS\0"),
439 AsmInstrData(0x00FEFF, 0x006EF3, 1,WP, RDX,MDE,PCX, C_REP+C_RARE+1, "REP OUTS\0"),
440 AsmInstrData(0x0000FF, 0x000037, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAA\0"),
441 AsmInstrData(0x0000FF, 0x00003F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAS\0"),
442 AsmInstrData(0x00FFFF, 0x000AD4, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAM\0"),
443 AsmInstrData(0x0000FF, 0x0000D4, 1,00, IM1,NNN,NNN, C_CMD+C_RARE+0, "AAM\0"),
444 AsmInstrData(0x00FFFF, 0x000AD5, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAD\0"),
445 AsmInstrData(0x0000FF, 0x0000D5, 1,00, IM1,NNN,NNN, C_CMD+C_RARE+0, "AAD\0"),
446 AsmInstrData(0x0000FF, 0x000027, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "DAA\0"),
447 AsmInstrData(0x0000FF, 0x00002F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "DAS\0"),
448 AsmInstrData(0x0000FF, 0x0000F4, 1,PR, NNN,NNN,NNN, C_PRI+C_RARE+0, "HLT\0"),
449 AsmInstrData(0x0000FF, 0x00000E, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
450 AsmInstrData(0x0000FF, 0x000016, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
451 AsmInstrData(0x0000FF, 0x00001E, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
452 AsmInstrData(0x0000FF, 0x000006, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
453 AsmInstrData(0x00FFFF, 0x00A00F, 2,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
454 AsmInstrData(0x00FFFF, 0x00A80F, 2,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH\0"),
455 AsmInstrData(0x0000FF, 0x00001F, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP\0"),
456 AsmInstrData(0x0000FF, 0x000007, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP\0"),
457 AsmInstrData(0x0000FF, 0x000017, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP\0"),
458 AsmInstrData(0x00FFFF, 0x00A10F, 2,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP\0"),
459 AsmInstrData(0x00FFFF, 0x00A90F, 2,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP\0"),
460 AsmInstrData(0x0000FF, 0x0000D7, 1,00, MXL,NNN,NNN, C_CMD+C_RARE+1, "XLAT\0"),
461 AsmInstrData(0x00FFFF, 0x00BE0F, 2,00, REG,MR1,NNN, C_CMD+1, "MOVSX\0"),
462 AsmInstrData(0x00FFFF, 0x00B60F, 2,00, REG,MR1,NNN, C_CMD+1, "MOVZX\0"),
463 AsmInstrData(0x00FFFF, 0x00B70F, 2,00, REG,MR2,NNN, C_CMD+1, "MOVZX\0"),
464 AsmInstrData(0x0000FF, 0x00009B, 1,00, NNN,NNN,NNN, C_CMD+0, "WAIT\0"),
465 AsmInstrData(0x0000FF, 0x00009F, 1,00, PAH,PFL,NNN, C_CMD+C_RARE+0, "LAHF\0"),
466 AsmInstrData(0x0000FF, 0x00009E, 1,00, PFL,PAH,NNN, C_CMD+C_RARE+0, "SAHF\0"),
467 AsmInstrData(0x0000FF, 0x00009C, 1,00, NNN,NNN,NNN, C_PSH+0, "&PUSHF*\0"),
468 AsmInstrData(0x0000FF, 0x00009D, 1,00, NNN,NNN,NNN, C_FLG+0, "&POPF*\0"),
469 AsmInstrData(0x0000FF, 0x0000CD, 1,00, IM1,NNN,NNN, C_CAL+C_RARE+0, "INT\0"),
470 AsmInstrData(0x0000FF, 0x0000CC, 1,00, NNN,NNN,NNN, C_CAL+C_RARE+0, "INT3\0"),
471 AsmInstrData(0x0000FF, 0x0000CE, 1,00, NNN,NNN,NNN, C_CAL+C_RARE+0, "INTO\0"),
472 AsmInstrData(0x0000FF, 0x0000CF, 1,00, NNN,NNN,NNN, C_RTF+C_RARE+0, "&IRET*\0"),
473 AsmInstrData(0x00FFFF, 0x00900F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETO\0"),
474 AsmInstrData(0x00FFFF, 0x00910F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNO\0"),
475 AsmInstrData(0x00FFFF, 0x00920F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETB,SETC\0"),
476 AsmInstrData(0x00FFFF, 0x00930F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNB,SETNC\0"),
477 AsmInstrData(0x00FFFF, 0x00940F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETE,SETZ\0"),
478 AsmInstrData(0x00FFFF, 0x00950F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNE,SETNZ\0"),
479 AsmInstrData(0x00FFFF, 0x00960F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETBE,SETNA\0"),
480 AsmInstrData(0x00FFFF, 0x00970F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETA,SETNBE\0"),
481 AsmInstrData(0x00FFFF, 0x00980F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETS\0"),
482 AsmInstrData(0x00FFFF, 0x00990F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNS\0"),
483 AsmInstrData(0x00FFFF, 0x009A0F, 2,CC, MR1,NNN,NNN, C_CMD+C_RARE+0, "SETPE,SETP\0"),
484 AsmInstrData(0x00FFFF, 0x009B0F, 2,CC, MR1,NNN,NNN, C_CMD+C_RARE+0, "SETPO,SETNP\0"),
485 AsmInstrData(0x00FFFF, 0x009C0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETL,SETNGE\0"),
486 AsmInstrData(0x00FFFF, 0x009D0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETGE,SETNL\0"),
487 AsmInstrData(0x00FFFF, 0x009E0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETLE,SETNG\0"),
488 AsmInstrData(0x00FFFF, 0x009F0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETG,SETNLE\0"),
489 AsmInstrData(0x38FFFF, 0x20BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BT\0"),
490 AsmInstrData(0x38FFFF, 0x28BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTS\0"),
491 AsmInstrData(0x38FFFF, 0x30BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTR\0"),
492 AsmInstrData(0x38FFFF, 0x38BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTC\0"),
493 AsmInstrData(0x00FFFF, 0x00A30F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BT\0"),
494 AsmInstrData(0x00FFFF, 0x00AB0F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTS\0"),
495 AsmInstrData(0x00FFFF, 0x00B30F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTR\0"),
496 AsmInstrData(0x00FFFF, 0x00BB0F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTC\0"),
497 AsmInstrData(0x0000FF, 0x0000C5, 1,00, REG,MML,NNN, C_CMD+C_RARE+0, "LDS\0"),
498 AsmInstrData(0x0000FF, 0x0000C4, 1,00, REG,MML,NNN, C_CMD+C_RARE+0, "LES\0"),
499 AsmInstrData(0x00FFFF, 0x00B40F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LFS\0"),
500 AsmInstrData(0x00FFFF, 0x00B50F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LGS\0"),
501 AsmInstrData(0x00FFFF, 0x00B20F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LSS\0"),
502 AsmInstrData(0x0000FF, 0x000063, 1,00, MRG,REG,NNN, C_CMD+C_RARE+0, "ARPL\0"),
503 AsmInstrData(0x0000FF, 0x000062, 1,00, REG,MMB,NNN, C_CMD+C_RARE+0, "BOUND\0"),
504 AsmInstrData(0x00FFFF, 0x00BC0F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "BSF\0"),
505 AsmInstrData(0x00FFFF, 0x00BD0F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "BSR\0"),
506 AsmInstrData(0x00FFFF, 0x00060F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "CLTS\0"),
507 AsmInstrData(0x00FFFF, 0x00400F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVO\0"),
508 AsmInstrData(0x00FFFF, 0x00410F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNO\0"),
509 AsmInstrData(0x00FFFF, 0x00420F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVB,CMOVC\0"),
510 AsmInstrData(0x00FFFF, 0x00430F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNB,CMOVNC\0"),
511 AsmInstrData(0x00FFFF, 0x00440F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVE,CMOVZ\0"),
512 AsmInstrData(0x00FFFF, 0x00450F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNE,CMOVNZ\0"),
513 AsmInstrData(0x00FFFF, 0x00460F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVBE,CMOVNA\0"),
514 AsmInstrData(0x00FFFF, 0x00470F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVA,CMOVNBE\0"),
515 AsmInstrData(0x00FFFF, 0x00480F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVS\0"),
516 AsmInstrData(0x00FFFF, 0x00490F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNS\0"),
517 AsmInstrData(0x00FFFF, 0x004A0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVPE,CMOVP\0"),
518 AsmInstrData(0x00FFFF, 0x004B0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVPO,CMOVNP\0"),
519 AsmInstrData(0x00FFFF, 0x004C0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVL,CMOVNGE\0"),
520 AsmInstrData(0x00FFFF, 0x004D0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVGE,CMOVNL\0"),
521 AsmInstrData(0x00FFFF, 0x004E0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVLE,CMOVNG\0"),
522 AsmInstrData(0x00FFFF, 0x004F0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVG,CMOVNLE\0"),
523 AsmInstrData(0x00FEFF, 0x00B00F, 2,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "CMPXCHG\0"),
524 AsmInstrData(0x38FFFF, 0x08C70F, 2,00, MD8,NNN,NNN, C_CMD+C_RARE+1, "CMPXCHG8B\0"),
525 AsmInstrData(0x00FFFF, 0x00A20F, 2,00, NNN,NNN,NNN, C_CMD+0, "CPUID\0"),
526 AsmInstrData(0x00FFFF, 0x00080F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "INVD\0"),
527 AsmInstrData(0x00FFFF, 0x00020F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "LAR\0"),
528 AsmInstrData(0x00FFFF, 0x00030F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "LSL\0"),
529 AsmInstrData(0x38FFFF, 0x38010F, 2,PR, MR1,NNN,NNN, C_CMD+C_RARE+0, "INVLPG\0"),
530 AsmInstrData(0x00FFFF, 0x00090F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "WBINVD\0"),
531 AsmInstrData(0x38FFFF, 0x10010F, 2,PR, MM6,NNN,NNN, C_CMD+C_RARE+0, "LGDT\0"),
532 AsmInstrData(0x38FFFF, 0x00010F, 2,00, MM6,NNN,NNN, C_CMD+C_RARE+0, "SGDT\0"),
533 AsmInstrData(0x38FFFF, 0x18010F, 2,PR, MM6,NNN,NNN, C_CMD+C_RARE+0, "LIDT\0"),
534 AsmInstrData(0x38FFFF, 0x08010F, 2,00, MM6,NNN,NNN, C_CMD+C_RARE+0, "SIDT\0"),
535 AsmInstrData(0x38FFFF, 0x10000F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LLDT\0"),
536 AsmInstrData(0x38FFFF, 0x00000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "SLDT\0"),
537 AsmInstrData(0x38FFFF, 0x18000F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LTR\0"),
538 AsmInstrData(0x38FFFF, 0x08000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "STR\0"),
539 AsmInstrData(0x38FFFF, 0x30010F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LMSW\0"),
540 AsmInstrData(0x38FFFF, 0x20010F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "SMSW\0"),
541 AsmInstrData(0x38FFFF, 0x20000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "VERR\0"),
542 AsmInstrData(0x38FFFF, 0x28000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "VERW\0"),
543 AsmInstrData(0xC0FFFF, 0xC0220F, 2,PR, CRX,RR4,NNN, C_CMD+C_RARE+0, "MOV\0"),
544 AsmInstrData(0xC0FFFF, 0xC0200F, 2,00, RR4,CRX,NNN, C_CMD+C_RARE+0, "MOV\0"),
545 AsmInstrData(0xC0FFFF, 0xC0230F, 2,PR, DRX,RR4,NNN, C_CMD+C_RARE+0, "MOV\0"),
546 AsmInstrData(0xC0FFFF, 0xC0210F, 2,PR, RR4,DRX,NNN, C_CMD+C_RARE+0, "MOV\0"),
547 AsmInstrData(0x00FFFF, 0x00310F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDTSC\0"),
548 AsmInstrData(0x00FFFF, 0x00320F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDMSR\0"),
549 AsmInstrData(0x00FFFF, 0x00300F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "WRMSR\0"),
550 AsmInstrData(0x00FFFF, 0x00330F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDPMC\0"),
551 AsmInstrData(0x00FFFF, 0x00AA0F, 2,PR, NNN,NNN,NNN, C_RTF+C_RARE+0, "RSM\0"),
552 AsmInstrData(0x00FFFF, 0x000B0F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "UD2\0"),
553 AsmInstrData(0x00FFFF, 0x00340F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "SYSENTER\0"),
554 AsmInstrData(0x00FFFF, 0x00350F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "SYSEXIT\0"),
555 AsmInstrData(0x0000FF, 0x0000D6, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "SALC\0"),
556 // FPU instructions. Never change the order of instructions!
557 AsmInstrData(0x00FFFF, 0x00F0D9, 2,00, PS0,NNN,NNN, C_FLT+0, "F2XM1\0"),
558 AsmInstrData(0x00FFFF, 0x00E0D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FCHS\0"),
559 AsmInstrData(0x00FFFF, 0x00E1D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FABS\0"),
560 AsmInstrData(0x00FFFF, 0x00E2DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FCLEX\0"),
561 AsmInstrData(0x00FFFF, 0x00E3DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FINIT\0"),
562 AsmInstrData(0x00FFFF, 0x00F6D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FDECSTP\0"),
563 AsmInstrData(0x00FFFF, 0x00F7D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FINCSTP\0"),
564 AsmInstrData(0x00FFFF, 0x00E4D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FTST\0"),
565 AsmInstrData(0x00FFFF, 0x00FAD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSQRT\0"),
566 AsmInstrData(0x00FFFF, 0x00FED9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSIN\0"),
567 AsmInstrData(0x00FFFF, 0x00FFD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FCOS\0"),
568 AsmInstrData(0x00FFFF, 0x00FBD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSINCOS\0"),
569 AsmInstrData(0x00FFFF, 0x00F2D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FPTAN\0"),
570 AsmInstrData(0x00FFFF, 0x00F3D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FPATAN\0"),
571 AsmInstrData(0x00FFFF, 0x00F8D9, 2,00, PS1,PS0,NNN, C_FLT+0, "FPREM\0"),
572 AsmInstrData(0x00FFFF, 0x00F5D9, 2,00, PS1,PS0,NNN, C_FLT+0, "FPREM1\0"),
573 AsmInstrData(0x00FFFF, 0x00F1D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FYL2X\0"),
574 AsmInstrData(0x00FFFF, 0x00F9D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FYL2XP1\0"),
575 AsmInstrData(0x00FFFF, 0x00FCD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FRNDINT\0"),
576 AsmInstrData(0x00FFFF, 0x00E8D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLD1\0"),
577 AsmInstrData(0x00FFFF, 0x00E9D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDL2T\0"),
578 AsmInstrData(0x00FFFF, 0x00EAD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDL2E\0"),
579 AsmInstrData(0x00FFFF, 0x00EBD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDPI\0"),
580 AsmInstrData(0x00FFFF, 0x00ECD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDLG2\0"),
581 AsmInstrData(0x00FFFF, 0x00EDD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDLN2\0"),
582 AsmInstrData(0x00FFFF, 0x00EED9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDZ\0"),
583 AsmInstrData(0x00FFFF, 0x00FDD9, 2,00, PS0,PS1,NNN, C_FLT+0, "FSCALE\0"),
584 AsmInstrData(0x00FFFF, 0x00D0D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FNOP\0"),
585 AsmInstrData(0x00FFFF, 0x00E0DF, 2,FF, RAX,NNN,NNN, C_FLT+0, "FSTSW\0"),
586 AsmInstrData(0x00FFFF, 0x00E5D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FXAM\0"),
587 AsmInstrData(0x00FFFF, 0x00F4D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FXTRACT\0"),
588 AsmInstrData(0x00FFFF, 0x00D9DE, 2,00, PS0,PS1,NNN, C_FLT+0, "FCOMPP\0"),
589 AsmInstrData(0x00FFFF, 0x00E9DA, 2,00, PS0,PS1,NNN, C_FLT+0, "FUCOMPP\0"),
590 AsmInstrData(0x00F8FF, 0x00C0DD, 2,00, RST,NNN,NNN, C_FLT+0, "FFREE\0"),
591 AsmInstrData(0x00F8FF, 0x00C0DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVB\0"),
592 AsmInstrData(0x00F8FF, 0x00C8DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVE\0"),
593 AsmInstrData(0x00F8FF, 0x00D0DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVBE\0"),
594 AsmInstrData(0x00F8FF, 0x00D8DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVU\0"),
595 AsmInstrData(0x00F8FF, 0x00C0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNB\0"),
596 AsmInstrData(0x00F8FF, 0x00C8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNE\0"),
597 AsmInstrData(0x00F8FF, 0x00D0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNBE\0"),
598 AsmInstrData(0x00F8FF, 0x00D8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNU\0"),
599 AsmInstrData(0x00F8FF, 0x00F0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCOMI\0"),
600 AsmInstrData(0x00F8FF, 0x00F0DF, 2,00, RS0,RST,NNN, C_FLT+0, "FCOMIP\0"),
601 AsmInstrData(0x00F8FF, 0x00E8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FUCOMI\0"),
602 AsmInstrData(0x00F8FF, 0x00E8DF, 2,00, RS0,RST,NNN, C_FLT+0, "FUCOMIP\0"),
603 AsmInstrData(0x00F8FF, 0x00C0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FADD\0"),
604 AsmInstrData(0x00F8FF, 0x00C0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FADD\0"),
605 AsmInstrData(0x00F8FF, 0x00C0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FADDP\0"),
606 AsmInstrData(0x00F8FF, 0x00E0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FSUB\0"),
607 AsmInstrData(0x00F8FF, 0x00E8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FSUB\0"),
608 AsmInstrData(0x00F8FF, 0x00E8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBP\0"),
609 AsmInstrData(0x00F8FF, 0x00E8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FSUBR\0"),
610 AsmInstrData(0x00F8FF, 0x00E0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBR\0"),
611 AsmInstrData(0x00F8FF, 0x00E0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBRP\0"),
612 AsmInstrData(0x00F8FF, 0x00C8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FMUL\0"),
613 AsmInstrData(0x00F8FF, 0x00C8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FMUL\0"),
614 AsmInstrData(0x00F8FF, 0x00C8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FMULP\0"),
615 AsmInstrData(0x00F8FF, 0x00D0D8, 2,00, RST,PS0,NNN, C_FLT+0, "FCOM\0"),
616 AsmInstrData(0x00F8FF, 0x00D8D8, 2,00, RST,PS0,NNN, C_FLT+0, "FCOMP\0"),
617 AsmInstrData(0x00F8FF, 0x00E0DD, 2,00, RST,PS0,NNN, C_FLT+0, "FUCOM\0"),
618 AsmInstrData(0x00F8FF, 0x00E8DD, 2,00, RST,PS0,NNN, C_FLT+0, "FUCOMP\0"),
619 AsmInstrData(0x00F8FF, 0x00F0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FDIV\0"),
620 AsmInstrData(0x00F8FF, 0x00F8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FDIV\0"),
621 AsmInstrData(0x00F8FF, 0x00F8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVP\0"),
622 AsmInstrData(0x00F8FF, 0x00F8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FDIVR\0"),
623 AsmInstrData(0x00F8FF, 0x00F0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVR\0"),
624 AsmInstrData(0x00F8FF, 0x00F0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVRP\0"),
625 AsmInstrData(0x00F8FF, 0x00C0D9, 2,00, RST,NNN,NNN, C_FLT+0, "FLD\0"),
626 AsmInstrData(0x00F8FF, 0x00D0DD, 2,00, RST,PS0,NNN, C_FLT+0, "FST\0"),
627 AsmInstrData(0x00F8FF, 0x00D8DD, 2,00, RST,PS0,NNN, C_FLT+0, "FSTP\0"),
628 AsmInstrData(0x00F8FF, 0x00C8D9, 2,00, RST,PS0,NNN, C_FLT+0, "FXCH\0"),
629 AsmInstrData(0x0038FF, 0x0000D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FADD\0"),
630 AsmInstrData(0x0038FF, 0x0000DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FADD\0"),
631 AsmInstrData(0x0038FF, 0x0000DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIADD\0"),
632 AsmInstrData(0x0038FF, 0x0000DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIADD\0"),
633 AsmInstrData(0x0038FF, 0x0020D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FSUB\0"),
634 AsmInstrData(0x0038FF, 0x0020DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FSUB\0"),
635 AsmInstrData(0x0038FF, 0x0020DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FISUB\0"),
636 AsmInstrData(0x0038FF, 0x0020DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FISUB\0"),
637 AsmInstrData(0x0038FF, 0x0028D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FSUBR\0"),
638 AsmInstrData(0x0038FF, 0x0028DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FSUBR\0"),
639 AsmInstrData(0x0038FF, 0x0028DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FISUBR\0"),
640 AsmInstrData(0x0038FF, 0x0028DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FISUBR\0"),
641 AsmInstrData(0x0038FF, 0x0008D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FMUL\0"),
642 AsmInstrData(0x0038FF, 0x0008DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FMUL\0"),
643 AsmInstrData(0x0038FF, 0x0008DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIMUL\0"),
644 AsmInstrData(0x0038FF, 0x0008DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIMUL\0"),
645 AsmInstrData(0x0038FF, 0x0010D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FCOM\0"),
646 AsmInstrData(0x0038FF, 0x0010DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FCOM\0"),
647 AsmInstrData(0x0038FF, 0x0018D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FCOMP\0"),
648 AsmInstrData(0x0038FF, 0x0018DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FCOMP\0"),
649 AsmInstrData(0x0038FF, 0x0030D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FDIV\0"),
650 AsmInstrData(0x0038FF, 0x0030DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FDIV\0"),
651 AsmInstrData(0x0038FF, 0x0030DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIDIV\0"),
652 AsmInstrData(0x0038FF, 0x0030DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIDIV\0"),
653 AsmInstrData(0x0038FF, 0x0038D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FDIVR\0"),
654 AsmInstrData(0x0038FF, 0x0038DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FDIVR\0"),
655 AsmInstrData(0x0038FF, 0x0038DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIDIVR\0"),
656 AsmInstrData(0x0038FF, 0x0038DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIDIVR\0"),
657 AsmInstrData(0x0038FF, 0x0020DF, 1,00, MDA,NNN,NNN, C_FLT+C_RARE+1, "FBLD\0"),
658 AsmInstrData(0x0038FF, 0x0030DF, 1,00, MDA,PS0,NNN, C_FLT+C_RARE+1, "FBSTP\0"),
659 AsmInstrData(0x0038FF, 0x0010DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FICOM\0"),
660 AsmInstrData(0x0038FF, 0x0010DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FICOM\0"),
661 AsmInstrData(0x0038FF, 0x0018DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FICOMP\0"),
662 AsmInstrData(0x0038FF, 0x0018DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FICOMP\0"),
663 AsmInstrData(0x0038FF, 0x0000DF, 1,00, MD2,NNN,NNN, C_FLT+1, "FILD\0"),
664 AsmInstrData(0x0038FF, 0x0000DB, 1,00, MD4,NNN,NNN, C_FLT+1, "FILD\0"),
665 AsmInstrData(0x0038FF, 0x0028DF, 1,00, MD8,NNN,NNN, C_FLT+1, "FILD\0"),
666 AsmInstrData(0x0038FF, 0x0010DF, 1,00, MD2,PS0,NNN, C_FLT+1, "FIST\0"),
667 AsmInstrData(0x0038FF, 0x0010DB, 1,00, MD4,PS0,NNN, C_FLT+1, "FIST\0"),
668 AsmInstrData(0x0038FF, 0x0018DF, 1,00, MD2,PS0,NNN, C_FLT+1, "FISTP\0"),
669 AsmInstrData(0x0038FF, 0x0018DB, 1,00, MD4,PS0,NNN, C_FLT+1, "FISTP\0"),
670 AsmInstrData(0x0038FF, 0x0038DF, 1,00, MD8,PS0,NNN, C_FLT+1, "FISTP\0"),
671 AsmInstrData(0x0038FF, 0x0000D9, 1,00, MF4,NNN,NNN, C_FLT+1, "FLD\0"),
672 AsmInstrData(0x0038FF, 0x0000DD, 1,00, MF8,NNN,NNN, C_FLT+1, "FLD\0"),
673 AsmInstrData(0x0038FF, 0x0028DB, 1,00, MFA,NNN,NNN, C_FLT+1, "FLD\0"),
674 AsmInstrData(0x0038FF, 0x0010D9, 1,00, MF4,PS0,NNN, C_FLT+1, "FST\0"),
675 AsmInstrData(0x0038FF, 0x0010DD, 1,00, MF8,PS0,NNN, C_FLT+1, "FST\0"),
676 AsmInstrData(0x0038FF, 0x0018D9, 1,00, MF4,PS0,NNN, C_FLT+1, "FSTP\0"),
677 AsmInstrData(0x0038FF, 0x0018DD, 1,00, MF8,PS0,NNN, C_FLT+1, "FSTP\0"),
678 AsmInstrData(0x0038FF, 0x0038DB, 1,00, MFA,PS0,NNN, C_FLT+1, "FSTP\0"),
679 AsmInstrData(0x0038FF, 0x0028D9, 1,00, MB2,NNN,NNN, C_FLT+0, "FLDCW\0"),
680 AsmInstrData(0x0038FF, 0x0038D9, 1,00, MB2,NNN,NNN, C_FLT+0, "FSTCW\0"),
681 AsmInstrData(0x0038FF, 0x0020D9, 1,00, MFE,NNN,NNN, C_FLT+0, "FLDENV\0"),
682 AsmInstrData(0x0038FF, 0x0030D9, 1,00, MFE,NNN,NNN, C_FLT+0, "FSTENV\0"),
683 AsmInstrData(0x0038FF, 0x0020DD, 1,00, MFS,NNN,NNN, C_FLT+0, "FRSTOR\0"),
684 AsmInstrData(0x0038FF, 0x0030DD, 1,00, MFS,NNN,NNN, C_FLT+0, "FSAVE\0"),
685 AsmInstrData(0x0038FF, 0x0038DD, 1,00, MB2,NNN,NNN, C_FLT+0, "FSTSW\0"),
686 AsmInstrData(0x38FFFF, 0x08AE0F, 2,00, MFX,NNN,NNN, C_FLT+0, "FXRSTOR\0"),
687 AsmInstrData(0x38FFFF, 0x00AE0F, 2,00, MFX,NNN,NNN, C_FLT+0, "FXSAVE\0"),
688 AsmInstrData(0x00FFFF, 0x00E0DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FENI\0"),
689 AsmInstrData(0x00FFFF, 0x00E1DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FDISI\0"),
690 // MMX instructions. Length of MMX operand fields (in bytes) is added to the
691 // type, length of 0 means 8-byte MMX operand.
692 AsmInstrData(0x00FFFF, 0x00770F, 2,00, NNN,NNN,NNN, C_MMX+0, "EMMS\0"),
693 AsmInstrData(0x00FFFF, 0x006E0F, 2,00, RMX,MR4,NNN, C_MMX+0, "MOVD\0"),
694 AsmInstrData(0x00FFFF, 0x007E0F, 2,00, MR4,RMX,NNN, C_MMX+0, "MOVD\0"),
695 AsmInstrData(0x00FFFF, 0x006F0F, 2,00, RMX,MR8,NNN, C_MMX+0, "MOVQ\0"),
696 AsmInstrData(0x00FFFF, 0x007F0F, 2,00, MR8,RMX,NNN, C_MMX+0, "MOVQ\0"),
697 AsmInstrData(0x00FFFF, 0x00630F, 2,00, RMX,MR8,NNN, C_MMX+2, "PACKSSWB\0"),
698 AsmInstrData(0x00FFFF, 0x006B0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PACKSSDW\0"),
699 AsmInstrData(0x00FFFF, 0x00670F, 2,00, RMX,MR8,NNN, C_MMX+2, "PACKUSWB\0"),
700 AsmInstrData(0x00FFFF, 0x00FC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDB\0"),
701 AsmInstrData(0x00FFFF, 0x00FD0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDW\0"),
702 AsmInstrData(0x00FFFF, 0x00FE0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PADDD\0"),
703 AsmInstrData(0x00FFFF, 0x00F80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBB\0"),
704 AsmInstrData(0x00FFFF, 0x00F90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBW\0"),
705 AsmInstrData(0x00FFFF, 0x00FA0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSUBD\0"),
706 AsmInstrData(0x00FFFF, 0x00EC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDSB\0"),
707 AsmInstrData(0x00FFFF, 0x00ED0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDSW\0"),
708 AsmInstrData(0x00FFFF, 0x00E80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBSB\0"),
709 AsmInstrData(0x00FFFF, 0x00E90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBSW\0"),
710 AsmInstrData(0x00FFFF, 0x00DC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDUSB\0"),
711 AsmInstrData(0x00FFFF, 0x00DD0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDUSW\0"),
712 AsmInstrData(0x00FFFF, 0x00D80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBUSB\0"),
713 AsmInstrData(0x00FFFF, 0x00D90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBUSW\0"),
714 AsmInstrData(0x00FFFF, 0x00DB0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PAND\0"),
715 AsmInstrData(0x00FFFF, 0x00DF0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PANDN\0"),
716 AsmInstrData(0x00FFFF, 0x00740F, 2,00, RMX,MR8,NNN, C_MMX+1, "PCMPEQB\0"),
717 AsmInstrData(0x00FFFF, 0x00750F, 2,00, RMX,MR8,NNN, C_MMX+2, "PCMPEQW\0"),
718 AsmInstrData(0x00FFFF, 0x00760F, 2,00, RMX,MR8,NNN, C_MMX+4, "PCMPEQD\0"),
719 AsmInstrData(0x00FFFF, 0x00640F, 2,00, RMX,MR8,NNN, C_MMX+1, "PCMPGTB\0"),
720 AsmInstrData(0x00FFFF, 0x00650F, 2,00, RMX,MR8,NNN, C_MMX+2, "PCMPGTW\0"),
721 AsmInstrData(0x00FFFF, 0x00660F, 2,00, RMX,MR8,NNN, C_MMX+4, "PCMPGTD\0"),
722 AsmInstrData(0x00FFFF, 0x00F50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMADDWD\0"),
723 AsmInstrData(0x00FFFF, 0x00E50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULHW\0"),
724 AsmInstrData(0x00FFFF, 0x00D50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULLW\0"),
725 AsmInstrData(0x00FFFF, 0x00EB0F, 2,00, RMX,MR8,NNN, C_MMX+0, "POR\0"),
726 AsmInstrData(0x00FFFF, 0x00F10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSLLW\0"),
727 AsmInstrData(0x38FFFF, 0x30710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSLLW\0"),
728 AsmInstrData(0x00FFFF, 0x00F20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSLLD\0"),
729 AsmInstrData(0x38FFFF, 0x30720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSLLD\0"),
730 AsmInstrData(0x00FFFF, 0x00F30F, 2,00, RMX,MR8,NNN, C_MMX+0, "PSLLQ\0"),
731 AsmInstrData(0x38FFFF, 0x30730F, 2,00, MR8,IM1,NNN, C_MMX+0, "PSLLQ\0"),
732 AsmInstrData(0x00FFFF, 0x00E10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSRAW\0"),
733 AsmInstrData(0x38FFFF, 0x20710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSRAW\0"),
734 AsmInstrData(0x00FFFF, 0x00E20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSRAD\0"),
735 AsmInstrData(0x38FFFF, 0x20720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSRAD\0"),
736 AsmInstrData(0x00FFFF, 0x00D10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSRLW\0"),
737 AsmInstrData(0x38FFFF, 0x10710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSRLW\0"),
738 AsmInstrData(0x00FFFF, 0x00D20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSRLD\0"),
739 AsmInstrData(0x38FFFF, 0x10720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSRLD\0"),
740 AsmInstrData(0x00FFFF, 0x00D30F, 2,00, RMX,MR8,NNN, C_MMX+0, "PSRLQ\0"),
741 AsmInstrData(0x38FFFF, 0x10730F, 2,00, MR8,IM1,NNN, C_MMX+0, "PSRLQ\0"),
742 AsmInstrData(0x00FFFF, 0x00680F, 2,00, RMX,MR8,NNN, C_MMX+1, "PUNPCKHBW\0"),
743 AsmInstrData(0x00FFFF, 0x00690F, 2,00, RMX,MR8,NNN, C_MMX+2, "PUNPCKHWD\0"),
744 AsmInstrData(0x00FFFF, 0x006A0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PUNPCKHDQ\0"),
745 AsmInstrData(0x00FFFF, 0x00600F, 2,00, RMX,MR8,NNN, C_MMX+1, "PUNPCKLBW\0"),
746 AsmInstrData(0x00FFFF, 0x00610F, 2,00, RMX,MR8,NNN, C_MMX+2, "PUNPCKLWD\0"),
747 AsmInstrData(0x00FFFF, 0x00620F, 2,00, RMX,MR8,NNN, C_MMX+4, "PUNPCKLDQ\0"),
748 AsmInstrData(0x00FFFF, 0x00EF0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PXOR\0"),
749 // AMD extentions to MMX command set (including Athlon/PIII extentions).
750 AsmInstrData(0x00FFFF, 0x000E0F, 2,00, NNN,NNN,NNN, C_MMX+0, "FEMMS\0"),
751 AsmInstrData(0x38FFFF, 0x000D0F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCH\0"),
752 AsmInstrData(0x38FFFF, 0x080D0F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHW\0"),
753 AsmInstrData(0x00FFFF, 0x00F70F, 2,00, RMX,RR8,PDI, C_MMX+1, "MASKMOVQ\0"),
754 AsmInstrData(0x00FFFF, 0x00E70F, 2,00, MD8,RMX,NNN, C_MMX+0, "MOVNTQ\0"),
755 AsmInstrData(0x00FFFF, 0x00E00F, 2,00, RMX,MR8,NNN, C_MMX+1, "PAVGB\0"),
756 AsmInstrData(0x00FFFF, 0x00E30F, 2,00, RMX,MR8,NNN, C_MMX+2, "PAVGW\0"),
757 AsmInstrData(0x00FFFF, 0x00C50F, 2,00, RR4,RMX,IM1, C_MMX+2, "PEXTRW\0"),
758 AsmInstrData(0x00FFFF, 0x00C40F, 2,00, RMX,MR2,IM1, C_MMX+2, "PINSRW\0"),
759 AsmInstrData(0x00FFFF, 0x00EE0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMAXSW\0"),
760 AsmInstrData(0x00FFFF, 0x00DE0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PMAXUB\0"),
761 AsmInstrData(0x00FFFF, 0x00EA0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMINSW\0"),
762 AsmInstrData(0x00FFFF, 0x00DA0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PMINUB\0"),
763 AsmInstrData(0x00FFFF, 0x00D70F, 2,00, RG4,RR8,NNN, C_MMX+1, "PMOVMSKB\0"),
764 AsmInstrData(0x00FFFF, 0x00E40F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULHUW\0"),
765 AsmInstrData(0x38FFFF, 0x00180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHNTA\0"),
766 AsmInstrData(0x38FFFF, 0x08180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT0\0"),
767 AsmInstrData(0x38FFFF, 0x10180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT1\0"),
768 AsmInstrData(0x38FFFF, 0x18180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT2\0"),
769 AsmInstrData(0x00FFFF, 0x00F60F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSADBW\0"),
770 AsmInstrData(0x00FFFF, 0x00700F, 2,00, RMX,MR8,IM1, C_MMX+2, "PSHUFW\0"),
771 AsmInstrData(0xFFFFFF, 0xF8AE0F, 2,00, NNN,NNN,NNN, C_MMX+0, "SFENCE\0"),
772 // AMD 3DNow! instructions (including Athlon extentions).
773 AsmInstrData(0x00FFFF, 0xBF0F0F, 2,00, RMX,MR8,NNN, C_NOW+1, "PAVGUSB\0"),
774 AsmInstrData(0x00FFFF, 0x9E0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFADD\0"),
775 AsmInstrData(0x00FFFF, 0x9A0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFSUB\0"),
776 AsmInstrData(0x00FFFF, 0xAA0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFSUBR\0"),
777 AsmInstrData(0x00FFFF, 0xAE0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFACC\0"),
778 AsmInstrData(0x00FFFF, 0x900F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPGE\0"),
779 AsmInstrData(0x00FFFF, 0xA00F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPGT\0"),
780 AsmInstrData(0x00FFFF, 0xB00F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPEQ\0"),
781 AsmInstrData(0x00FFFF, 0x940F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMIN\0"),
782 AsmInstrData(0x00FFFF, 0xA40F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMAX\0"),
783 AsmInstrData(0x00FFFF, 0x0D0F0F, 2,00, R3D,MR8,NNN, C_NOW+4, "PI2FD\0"),
784 AsmInstrData(0x00FFFF, 0x1D0F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PF2ID\0"),
785 AsmInstrData(0x00FFFF, 0x960F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCP\0"),
786 AsmInstrData(0x00FFFF, 0x970F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRSQRT\0"),
787 AsmInstrData(0x00FFFF, 0xB40F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMUL\0"),
788 AsmInstrData(0x00FFFF, 0xA60F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCPIT1\0"),
789 AsmInstrData(0x00FFFF, 0xA70F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRSQIT1\0"),
790 AsmInstrData(0x00FFFF, 0xB60F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCPIT2\0"),
791 AsmInstrData(0x00FFFF, 0xB70F0F, 2,00, RMX,MR8,NNN, C_NOW+2, "PMULHRW\0"),
792 AsmInstrData(0x00FFFF, 0x1C0F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PF2IW\0"),
793 AsmInstrData(0x00FFFF, 0x8A0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFNACC\0"),
794 AsmInstrData(0x00FFFF, 0x8E0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFPNACC\0"),
795 AsmInstrData(0x00FFFF, 0x0C0F0F, 2,00, R3D,MR8,NNN, C_NOW+4, "PI2FW\0"),
796 AsmInstrData(0x00FFFF, 0xBB0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PSWAPD\0"),
797 // Some alternative mnemonics for Assembler, not used by Disassembler (so implicit pseudooperands are not marked).
798 AsmInstrData(0x0000FF, 0x0000A6, 1,00, NNN,NNN,NNN, C_CMD+0, "CMPSB\0"),
799 AsmInstrData(0x00FFFF, 0x00A766, 2,00, NNN,NNN,NNN, C_CMD+0, "CMPSW\0"),
800 AsmInstrData(0x0000FF, 0x0000A7, 1,00, NNN,NNN,NNN, C_CMD+0, "CMPSD\0"),
801 AsmInstrData(0x0000FF, 0x0000AC, 1,00, NNN,NNN,NNN, C_CMD+0, "LODSB\0"),
802 AsmInstrData(0x00FFFF, 0x00AD66, 2,00, NNN,NNN,NNN, C_CMD+0, "LODSW\0"),
803 AsmInstrData(0x0000FF, 0x0000AD, 1,00, NNN,NNN,NNN, C_CMD+0, "LODSD\0"),
804 AsmInstrData(0x0000FF, 0x0000A4, 1,00, NNN,NNN,NNN, C_CMD+0, "MOVSB\0"),
805 AsmInstrData(0x00FFFF, 0x00A566, 2,00, NNN,NNN,NNN, C_CMD+0, "MOVSW\0"),
806 AsmInstrData(0x0000FF, 0x0000A5, 1,00, NNN,NNN,NNN, C_CMD+0, "MOVSD\0"),
807 AsmInstrData(0x0000FF, 0x0000AE, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASB\0"),
808 AsmInstrData(0x00FFFF, 0x00AF66, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASW\0"),
809 AsmInstrData(0x0000FF, 0x0000AF, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASD\0"),
810 AsmInstrData(0x0000FF, 0x0000AA, 1,00, NNN,NNN,NNN, C_CMD+0, "STOSB\0"),
811 AsmInstrData(0x00FFFF, 0x00AB66, 2,00, NNN,NNN,NNN, C_CMD+0, "STOSW\0"),
812 AsmInstrData(0x0000FF, 0x0000AB, 1,00, NNN,NNN,NNN, C_CMD+0, "STOSD\0"),
813 AsmInstrData(0x00FFFF, 0x00A4F3, 1,00, NNN,NNN,NNN, C_REP+0, "REP MOVSB\0"),
814 AsmInstrData(0xFFFFFF, 0xA5F366, 2,00, NNN,NNN,NNN, C_REP+0, "REP MOVSW\0"),
815 AsmInstrData(0x00FFFF, 0x00A5F3, 1,00, NNN,NNN,NNN, C_REP+0, "REP MOVSD\0"),
816 AsmInstrData(0x00FFFF, 0x00ACF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP LODSB\0"),
817 AsmInstrData(0xFFFFFF, 0xADF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP LODSW\0"),
818 AsmInstrData(0x00FFFF, 0x00ADF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP LODSD\0"),
819 AsmInstrData(0x00FFFF, 0x00AAF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP STOSB\0"),
820 AsmInstrData(0xFFFFFF, 0xABF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP STOSW\0"),
821 AsmInstrData(0x00FFFF, 0x00ABF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP STOSD\0"),
822 AsmInstrData(0x00FFFF, 0x00A6F3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSB\0"),
823 AsmInstrData(0xFFFFFF, 0xA7F366, 2,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSW\0"),
824 AsmInstrData(0x00FFFF, 0x00A7F3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSD\0"),
825 AsmInstrData(0x00FFFF, 0x00AEF3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE SCASB\0"),
826 AsmInstrData(0xFFFFFF, 0xAFF366, 2,00, NNN,NNN,NNN, C_REP+0, "REPE SCASW\0"),
827 AsmInstrData(0x00FFFF, 0x00AFF3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE SCASD\0"),
828 AsmInstrData(0x00FFFF, 0x00A6F2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSB\0"),
829 AsmInstrData(0xFFFFFF, 0xA7F266, 2,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSW\0"),
830 AsmInstrData(0x00FFFF, 0x00A7F2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSD\0"),
831 AsmInstrData(0x00FFFF, 0x00AEF2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASB\0"),
832 AsmInstrData(0xFFFFFF, 0xAFF266, 2,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASW\0"),
833 AsmInstrData(0x00FFFF, 0x00AFF2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASD\0"),
834 AsmInstrData(0x0000FF, 0x00006C, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSB\0"),
835 AsmInstrData(0x00FFFF, 0x006D66, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSW\0"),
836 AsmInstrData(0x0000FF, 0x00006D, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSD\0"),
837 AsmInstrData(0x0000FF, 0x00006E, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSB\0"),
838 AsmInstrData(0x00FFFF, 0x006F66, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSW\0"),
839 AsmInstrData(0x0000FF, 0x00006F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSD\0"),
840 AsmInstrData(0x00FFFF, 0x006CF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP INSB\0"),
841 AsmInstrData(0xFFFFFF, 0x6DF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP INSW\0"),
842 AsmInstrData(0x00FFFF, 0x006DF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP INSD\0"),
843 AsmInstrData(0x00FFFF, 0x006EF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP OUTSB\0"),
844 AsmInstrData(0xFFFFFF, 0x6FF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP OUTSW\0"),
845 AsmInstrData(0x00FFFF, 0x006FF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP OUTSD\0"),
846 AsmInstrData(0x0000FF, 0x0000E1, 1,00, JOB,NNN,NNN, C_JMC+0, "$LOOP*Z\0"),
847 AsmInstrData(0x0000FF, 0x0000E0, 1,00, JOB,NNN,NNN, C_JMC+0, "$LOOP*NZ\0"),
848 AsmInstrData(0x0000FF, 0x00009B, 1,00, NNN,NNN,NNN, C_CMD+0, "FWAIT\0"),
849 AsmInstrData(0x0000FF, 0x0000D7, 1,00, NNN,NNN,NNN, C_CMD+0, "XLATB\0"),
850 AsmInstrData(0x00FFFF, 0x00C40F, 2,00, RMX,RR4,IM1, C_MMX+2, "PINSRW\0"),
851 AsmInstrData(0x00FFFF, 0x0020CD, 2,00, VXD,NNN,NNN, C_CAL+C_RARE+0, "VxDCall\0"),
852 // Pseudocommands used by Assembler for masked search only.
853 AsmInstrData(0x0000F0, 0x000070, 1,CC, JOB,NNN,NNN, C_JMC+0, "JCC\0"),
854 AsmInstrData(0x00F0FF, 0x00800F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JCC\0"),
855 AsmInstrData(0x00F0FF, 0x00900F, 2,CC, MR1,NNN,NNN, C_CMD+1, "SETCC\0"),
856 AsmInstrData(0x00F0FF, 0x00400F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVCC\0"),
859 // ////////////////////////////////////////////////////////////////////////// //
860 // Scanner modes.
861 enum SA_NAME = 0x0001; // Don't try to decode labels
863 enum MAX_PRIO = 10;
865 // Types of input tokens reported by scanner.
866 enum {
867 SCAN_EOL = 0, // End of line
868 SCAN_REG8, // 8-bit register
869 SCAN_REG16, // 16-bit register
870 SCAN_REG32, // 32-bit register
871 SCAN_SEG, // Segment register
872 SCAN_FPU, // FPU register
873 SCAN_MMX, // MMX register
874 SCAN_CR, // Control register
875 SCAN_DR, // Debug register
876 SCAN_OPSIZE, // Operand size modifier
877 SCAN_JMPSIZE, // Jump size modifier
878 SCAN_LOCAL, // Address on stack in form LOCAL.decimal
879 SCAN_ARG, // Address on stack in form ARG.decimal
881 SCAN_PTR = 20, // PTR in MASM addressing statements
882 SCAN_REP, // REP prefix
883 SCAN_REPE, // REPE prefix
884 SCAN_REPNE, // REPNE prefix
885 SCAN_LOCK, // LOCK prefix
886 SCAN_NAME, // Command or label
887 SCAN_UCONST, // Unsigned integer constant
888 SCAN_DCONST, // Signed integer constant
889 SCAN_OFS, // Undefined constant
890 SCAN_FCONST, // Floating-point constant
891 SCAN_EIP, // Register EIP
892 SCAN_SIGNED, // Keyword "SIGNED" (in expressions)
893 SCAN_UNSIGNED, // Keyword "UNSIGNED" (in expressions)
894 SCAN_CHAR, // Keyword "CHAR" (in expressions)
895 SCAN_FLOAT, // Keyword "FLOAT" (in expressions)
896 SCAN_DOUBLE, // Keyword "DOUBLE" (in expressions)
897 SCAN_FLOAT10, // Keyword "FLOAT10" (in expressions)
898 SCAN_STRING, // Keyword "STRING" (in expressions)
899 SCAN_UNICODE, // Keyword "UNICODE" (in expressions)
900 SCAN_MSG, // Pseudovariable MSG (in expressions)
901 SCAN_DEFB, // DEFB byte
902 SCAN_DEFW, // DEFW byte
903 SCAN_DEFD, // DEFD byte
905 SCAN_SYMB, // Any other character
907 SCAN_ERR = 255, // Definitely bad item
910 // Definition used by Assembler to report command matching errors.
911 enum MA_JMP = 0x0001; // Invalid jump size modifier
912 enum MA_NOP = 0x0002; // Wrong number of operands
913 enum MA_TYP = 0x0004; // Bad operand type
914 enum MA_NOS = 0x0008; // Explicit operand size expected
915 enum MA_SIZ = 0x0010; // Bad operand size
916 enum MA_DIF = 0x0020; // Different operand sizes
917 enum MA_SEG = 0x0040; // Invalid segment register
918 enum MA_RNG = 0x0080; // Constant out of expected range
920 struct AsmOperand {
921 int type; // Operand type, see beginning of file
922 int size; // Operand size or 0 if yet unknown
923 int index; // Index or other register
924 int scale; // Scale
925 int base; // Base register if present
926 int offset; // Immediate value or offset
927 int anyoffset; // Offset is present but undefined
928 int segment; // Segment in address if present
929 int jmpmode; // Specified jump size
932 struct AsmScanData {
933 char[4096] acommand; // 0-terminated copy
934 const(char)* asmcmd; // Pointer to 0-terminated source line
935 int scan; // Type of last scanned element
936 int prio; // Priority of operation (0: highest)
937 char[TEXTLEN] sdata; // Last scanned name (depends on type)
938 int idata; // Last scanned value
939 real fdata; // Floating-point number
940 string asmerror; // Explanation of last error, or null
941 uint stpc; // starting pc (for '$')
942 bool defaultHex; // default number base is hex
943 bool inMath; // true: don't convert '][' to '+'
944 bool noExprs; // true: no expression parsing
946 void skipBlanks () nothrow @nogc {
947 while (*asmcmd > 0 && *asmcmd <= ' ') ++asmcmd;
950 auto save () nothrow @nogc { pragma(inline, true); return Save(asmcmd, scan, idata, fdata); }
951 void restore() (in auto ref Save sv) { pragma(inline, true); asmcmd = sv.asmcmd; scan = sv.scan; idata = sv.idata; fdata = sv.idata; }
953 private:
954 static struct Save {
955 const(char)* asmcmd;
956 int scan;
957 int idata;
958 real fdata;
962 private template S2toI(string s) if (s.length == 2) {
963 enum S2toI = cast(int)s[0]|((cast(int)s[1])<<8);
966 // Simple and slightly recursive scanner shared by Assemble(). The scanner is
967 // straightforward and ineffective, but high speed is not a must here. As
968 // input, it uses global pointer to source line asmcmd. On exit, it fills in
969 // global variables scan, prio, sdata, idata and/or fdata. If some error is
970 // detected, asmerror points to error message, otherwise asmerror remains
971 // unchanged.
972 private void strupr (char* s) {
973 import core.stdc.ctype : toupper;
974 while (*s) {
975 *s = cast(char)toupper(*s);
976 ++s;
980 private void strcpyx (char* d, const(char)[] s) {
981 import core.stdc.string : memcpy;
982 if (d is null) return;
983 if (s.length == 0) {
984 *d = 0;
985 } else {
986 memcpy(d, s.ptr, s.length);
987 d[s.length] = 0;
991 private void xstrcpy (char[] d, const(char)* s) {
992 if (d.length == 0) return;
993 uint pos;
994 if (s !is null) {
995 while (*s) {
996 if (pos >= d.length) break;
997 d.ptr[pos++] = *s++;
1000 if (pos < d.length) d.ptr[pos] = 0;
1003 private void xstrcpyx (char[] d, const(char)[] s) {
1004 if (d.length == 0) return;
1005 uint pos;
1006 foreach (char ch; s) {
1007 if (ch == 0 || pos >= d.length) break;
1008 d.ptr[pos++] = ch;
1010 if (pos < d.length) d.ptr[pos] = 0;
1013 private int strnicmp (const(char)* s0, const(char)* s1, int len) {
1014 import core.stdc.ctype : toupper;
1015 if (len < 1) return 0;
1016 while (len-- > 0) {
1017 int c0 = toupper(*s0++);
1018 int c1 = toupper(*s1++);
1019 if (c0 != c1) return (c0 < c1 ? -1 : 1);
1020 if (c0 == 0) return -1;
1021 if (c1 == 0) return 1;
1023 return 0;
1026 static int hdig (char ch) {
1027 if (ch >= '0' && ch <= '9') return ch-'0';
1028 if (ch >= 'A' && ch <= 'F') return ch-'A'+10;
1029 if (ch >= 'a' && ch <= 'f') return ch-'a'+10;
1030 return -1;
1034 private void scanasm (ref AsmScanData scdata, int mode, scope ResolveSymCB resolver) {
1035 import core.stdc.ctype : isalpha, isalnum, isdigit, toupper, isxdigit;
1036 import core.stdc.string : strcmp, strcpy;
1038 static struct MathOp {
1039 int type = -1;
1040 int ival;
1041 real fval;
1043 this (in ref AsmScanData scdata) {
1044 if (scdata.scan == SCAN_UCONST || scdata.scan == SCAN_DCONST) {
1045 type = scdata.scan;
1046 ival = scdata.idata;
1047 } else if (scdata.scan == SCAN_FCONST) {
1048 type = SCAN_FCONST;
1049 fval = scdata.fdata;
1050 } else {
1051 type = -1; // invalid
1055 @property bool valid () const pure nothrow @safe @nogc { return (type > 0); }
1056 @property bool isAnyInt () const pure nothrow @safe @nogc { return (type == SCAN_UCONST || type == SCAN_DCONST); }
1057 @property bool isSignedInt () const pure nothrow @safe @nogc { return (type == SCAN_DCONST); }
1058 @property bool isFloat () const pure nothrow @safe @nogc { return (type == SCAN_FCONST); }
1060 void put (ref AsmScanData scdata) {
1061 if (!valid) return;
1062 scdata.scan = type;
1063 if (isAnyInt) scdata.idata = ival; else scdata.fdata = fval;
1066 // upgrade both this and op if necessary
1067 bool upgradeType (ref MathOp op) {
1068 if (!op.valid || !valid) return false;
1069 if (isFloat) {
1070 if (op.isAnyInt) {
1071 op.type = SCAN_FCONST;
1072 if (op.isSignedInt) op.fval = op.ival; else op.fval = cast(uint)op.ival;
1074 } else if (isAnyInt) {
1075 if (op.isFloat) {
1076 if (isSignedInt) fval = ival; else fval = cast(uint)ival;
1077 type = SCAN_FCONST;
1078 return true;
1080 if (!isSignedInt || !op.isSignedInt) { type = SCAN_UCONST; op.type = SCAN_UCONST; }
1081 } else {
1082 assert(0, "wtf?!");
1084 return true;
1087 bool doMath (int op, MathOp op2) {
1088 enum LogOpMixin(string op) = "if (isFloat) { type = SCAN_UCONST; ival = (fval != 0 "~op~" op2.fval != 0); } else { type = SCAN_UCONST; ival = (ival != 0 "~op~" op2.ival != 0); }";
1089 enum CmpOpMixin(string op) = "if (isFloat) { type = SCAN_UCONST; ival = (fval "~op~" op2.fval); } else { type = SCAN_UCONST; ival = (ival "~op~" op2.ival); }";
1091 if (!upgradeType(op2)) { type = -1; return false; }
1092 switch (op) {
1093 case S2toI!("||"): mixin(LogOpMixin!"||"); break;
1094 case S2toI!("&&"): mixin(LogOpMixin!"&&"); break;
1095 case S2toI!("=="): mixin(CmpOpMixin!"=="); break;
1096 case S2toI!("!="): mixin(CmpOpMixin!"!="); break;
1097 case S2toI!("<="): mixin(CmpOpMixin!"<="); break;
1098 case S2toI!(">="): mixin(CmpOpMixin!">="); break;
1099 case '<': mixin(CmpOpMixin!"<"); break;
1100 case '>': mixin(CmpOpMixin!">"); break;
1101 case S2toI!("<<"):
1102 if (isFloat || op2.ival < 0 || op2.ival > 31) { type = -1; return false; }
1103 if (op2.isSignedInt) {
1104 ival <<= op2.ival;
1105 } else {
1106 ival = (cast(uint)ival)<<op2.ival;
1108 break;
1109 case S2toI!(">>"):
1110 if (isFloat || op2.ival < 0 || op2.ival > 31) { type = -1; return false; }
1111 if (op2.isSignedInt) {
1112 ival >>= op2.ival;
1113 } else {
1114 ival = (cast(uint)ival)>>op2.ival;
1116 break;
1117 case '|':
1118 if (isFloat) { type = -1; return false; }
1119 ival |= op2.ival;
1120 break;
1121 case '^':
1122 if (isFloat) { type = -1; return false; }
1123 ival ^= op2.ival;
1124 break;
1125 case '&':
1126 if (isFloat) { type = -1; return false; }
1127 ival &= op2.ival;
1128 break;
1129 case '+':
1130 if (isFloat) fval += op2.fval; else ival += op2.ival;
1131 break;
1132 case '-':
1133 if (isFloat) fval -= op2.fval; else ival -= op2.ival;
1134 break;
1135 case '*':
1136 if (isFloat) fval *= op2.fval;
1137 else if (op2.isSignedInt) ival *= op2.ival;
1138 else ival = cast(uint)ival*cast(uint)op2.ival;
1139 break;
1140 case '/':
1141 if ((isFloat && fval == 0) || (isAnyInt && ival == 0)) { type = -2; return false; }
1142 if (isFloat) fval /= op2.fval;
1143 else if (op2.isSignedInt) ival /= op2.ival;
1144 else ival = cast(uint)ival/cast(uint)op2.ival;
1145 break;
1146 case '%':
1147 if ((isFloat && fval == 0) || (isAnyInt && ival == 0)) { type = -2; return false; }
1148 if (isFloat) fval %= op2.fval;
1149 else if (op2.isSignedInt) ival %= op2.ival;
1150 else ival = cast(uint)ival%cast(uint)op2.ival;
1151 break;
1152 default: type = -1; return false;
1154 return true;
1158 MathOp doExpr (int prio) {
1159 if (prio == 0) {
1160 // term
1161 auto saved = scdata.save;
1162 scdata.prio = 0;
1163 scanasm(scdata, 0, resolver);
1164 if (scdata.prio <= 0) {
1165 if (scdata.scan == SCAN_UCONST || scdata.scan == SCAN_DCONST || scdata.scan == SCAN_FCONST) {
1166 return MathOp(scdata);
1167 } else if (scdata.scan == SCAN_SYMB && scdata.idata == '(') {
1168 auto op = doExpr(MAX_PRIO);
1169 scdata.prio = 0;
1170 scanasm(scdata, 0, resolver);
1171 if (scdata.scan != SCAN_SYMB || scdata.idata != ')') {
1172 scdata.restore(saved);
1173 scdata.asmerror = "')' expected";
1174 scdata.scan = SCAN_ERR;
1175 return MathOp();
1177 return op;
1180 scdata.restore(saved);
1181 scdata.asmerror = "invalid math";
1182 scdata.scan = SCAN_ERR;
1183 return MathOp();
1186 auto op1 = doExpr(prio-1);
1187 if (!op1.valid) return op1;
1188 for (;;) {
1189 auto saved = scdata.save;
1190 scdata.prio = 0;
1191 scanasm(scdata, 0, resolver);
1192 if (scdata.scan == SCAN_SYMB && scdata.prio == prio) {
1193 auto op = scdata.idata;
1194 // check if this is not a register or keyword
1196 auto sv1 = scdata.save;
1197 scanasm(scdata, SA_NAME, resolver);
1198 if (scdata.scan != SCAN_SYMB) {
1199 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST && scdata.scan != SCAN_FCONST) {
1200 // alas, abort right here
1201 scdata.restore(saved);
1202 break;
1205 scdata.restore(sv1);
1207 auto op2 = doExpr(prio-1);
1208 if (!op2.valid) { scdata.restore(saved); return op2; }
1209 if (!op1.upgradeType(op2)) { scdata.asmerror = "invalid math operation"; scdata.scan = SCAN_ERR; return MathOp(); }
1210 if (!op1.doMath(op, op2)) { scdata.asmerror = "invalid math operation"; scdata.scan = SCAN_ERR; return MathOp(); }
1211 } else {
1212 scdata.restore(saved);
1213 break;
1216 return op1;
1219 void doExpression () {
1220 auto op = doExpr(MAX_PRIO);
1221 if (op.valid) op.put(scdata);
1224 int i, j, base, maxdigit;
1225 int decimal, hex;
1226 real floating, divisor;
1227 char[TEXTLEN] s;
1228 const(char)* pcmd;
1230 scdata.sdata[0] = '\0';
1231 scdata.idata = 0;
1232 if (scdata.asmcmd is null) { scdata.asmerror = "null input line"; scdata.scan = SCAN_ERR; return; }
1233 scdata.skipBlanks(); // Skip leading spaces
1234 if (*scdata.asmcmd == '\0' || *scdata.asmcmd == ';') { scdata.scan = SCAN_EOL; return; } // Empty line
1235 if (isalpha(*scdata.asmcmd) || *scdata.asmcmd == '_' || *scdata.asmcmd == '@') {
1236 // Some keyword or identifier
1237 scdata.sdata[0] = *scdata.asmcmd++;
1238 i = 1;
1239 while ((isalnum(*scdata.asmcmd) || *scdata.asmcmd == '_' || *scdata.asmcmd == '@' || *scdata.asmcmd == '.' || *scdata.asmcmd == '$') && i < scdata.sdata.length) scdata.sdata[i++] = *scdata.asmcmd++;
1240 if (i >= scdata.sdata.length) { scdata.asmerror = "Too long identifier"; scdata.scan = SCAN_ERR; return; }
1241 auto symname = (scdata.asmcmd-i)[0..i];
1242 scdata.sdata[i] = '\0';
1243 scdata.skipBlanks(); // Skip trailing spaces
1244 strcpy(s.ptr, scdata.sdata.ptr);
1245 strupr(s.ptr);
1246 // j == 8 means "any register"
1247 for (j = 0; j <= 8; ++j) {
1248 if (strcmp(s.ptr, regname[0][j].ptr) != 0) continue;
1249 // 8-bit register
1250 scdata.idata = j;
1251 scdata.scan = SCAN_REG8;
1252 return;
1254 for (j = 0; j <= 8; ++j) {
1255 if (strcmp(s.ptr, regname[1][j].ptr) != 0) continue;
1256 // 16-bit register
1257 scdata.idata = j;
1258 scdata.scan = SCAN_REG16;
1259 return;
1261 for (j = 0; j <= 8; ++j) {
1262 if (strcmp(s.ptr, regname[2][j].ptr) != 0) continue;
1263 // 32-bit register
1264 scdata.idata = j;
1265 scdata.scan = SCAN_REG32;
1266 return;
1268 for (j = 0; j < 6; ++j) {
1269 if (strcmp(s.ptr, segname[j].ptr) != 0) continue;
1270 // Segment register
1271 scdata.idata = j;
1272 scdata.scan = SCAN_SEG;
1273 scdata.skipBlanks(); // Skip trailing spaces
1274 return;
1276 if (strcmp(s.ptr, "ST") == 0) {
1277 // FPU register
1278 pcmd = scdata.asmcmd;
1279 scanasm(scdata, SA_NAME, resolver);
1280 if (scdata.scan != SCAN_SYMB || scdata.idata != '(') {
1281 // Undo last scan
1282 scdata.asmcmd = pcmd;
1283 scdata.idata = 0;
1284 scdata.scan = SCAN_FPU;
1285 return;
1287 scanasm(scdata, SA_NAME, resolver);
1288 j = scdata.idata;
1289 if ((scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST) || scdata.idata < 0 || scdata.idata > 7) {
1290 scdata.asmerror = "FPU registers have indexes 0 to 7";
1291 scdata.scan = SCAN_ERR;
1292 return;
1294 scanasm(scdata, SA_NAME, resolver);
1295 if (scdata.scan != SCAN_SYMB || scdata.idata != ')') {
1296 scdata.asmerror = "Closing parenthesis expected";
1297 scdata.scan = SCAN_ERR;
1298 return;
1300 scdata.idata = j;
1301 scdata.scan = SCAN_FPU;
1302 return;
1304 for (j = 0; j <= 8; ++j) {
1305 if (strcmp(s.ptr, fpuname[j].ptr) != 0) continue;
1306 // FPU register (alternative coding)
1307 scdata.idata = j;
1308 scdata.scan = SCAN_FPU;
1309 return;
1311 for (j = 0; j <= 8; ++j) {
1312 if (strcmp(s.ptr, mmxname[j].ptr) != 0) continue;
1313 // MMX register
1314 scdata.idata = j;
1315 scdata.scan = SCAN_MMX;
1316 return;
1318 for (j = 0; j <= 8; ++j) {
1319 if (strcmp(s.ptr, crname[j].ptr) != 0) continue;
1320 // Control register
1321 scdata.idata = j;
1322 scdata.scan = SCAN_CR;
1323 return;
1325 for (j = 0; j <= 8; ++j) {
1326 if (strcmp(s.ptr, drname[j].ptr) != 0) continue;
1327 // Debug register
1328 scdata.idata = j;
1329 scdata.scan = SCAN_DR;
1330 return;
1332 for (j = 0; j < sizename.length; ++j) {
1333 if (strcmp(s.ptr, sizename[j].ptr) != 0) continue;
1334 pcmd = scdata.asmcmd;
1335 scanasm(scdata, SA_NAME, resolver);
1336 if (scdata.scan != SCAN_PTR) scdata.asmcmd = pcmd; // Fetch non-functional "PTR"
1337 // Operand (data) size in bytes
1338 scdata.idata = j;
1339 scdata.scan = SCAN_OPSIZE;
1340 return;
1342 if (strcmp(s.ptr, "EIP") == 0) { scdata.scan = SCAN_EIP; scdata.idata = 0; return; } // Register EIP
1343 if (strcmp(s.ptr, "SHORT") == 0) { scdata.scan = SCAN_JMPSIZE; scdata.idata = 1; return; } // Relative jump has 1-byte offset
1344 if (strcmp(s.ptr, "LONG") == 0) { scdata.scan = SCAN_JMPSIZE; scdata.idata = 2; return; } // Relative jump has 4-byte offset
1345 if (strcmp(s.ptr, "NEAR") == 0) { scdata.scan = SCAN_JMPSIZE; scdata.idata = 4; return; } // Jump within same code segment
1346 if (strcmp(s.ptr, "FAR") == 0) { scdata.scan = SCAN_JMPSIZE; scdata.idata = 8; return; } // Jump to different code segment
1347 if (strcmp(s.ptr, "LOCAL") == 0 && *scdata.asmcmd == '.') {
1348 ++scdata.asmcmd;
1349 scdata.skipBlanks(); // Skip trailing spaces
1350 if (!isdigit(*scdata.asmcmd)) {
1351 scdata.asmerror = "Integer number expected";
1352 scdata.scan = SCAN_ERR;
1353 return;
1355 while (isdigit(*scdata.asmcmd)) scdata.idata = scdata.idata*10+(*scdata.asmcmd++)-'0'; // LOCAL index is decimal number!
1356 scdata.scan = SCAN_LOCAL;
1357 return;
1359 if (strcmp(s.ptr, "ARG") == 0 && *scdata.asmcmd == '.') {
1360 ++scdata.asmcmd;
1361 scdata.skipBlanks(); // Skip trailing spaces
1362 if (!isdigit(*scdata.asmcmd)) {
1363 scdata.asmerror = "Integer number expected";
1364 scdata.scan = SCAN_ERR;
1365 return;
1367 while (isdigit(*scdata.asmcmd)) scdata.idata = scdata.idata*10+(*scdata.asmcmd++)-'0'; // ARG index is decimal number!
1368 scdata.scan = SCAN_ARG;
1369 return;
1371 if (strcmp(s.ptr, "REP") == 0) { scdata.scan = SCAN_REP; return; } // REP prefix
1372 if (strcmp(s.ptr, "REPE") == 0 || strcmp(s.ptr, "REPZ") == 0) { scdata.scan = SCAN_REPE; return; } // REPE prefix
1373 if (strcmp(s.ptr, "REPNE") == 0 || strcmp(s.ptr, "REPNZ") == 0) { scdata.scan = SCAN_REPNE; return; } // REPNE prefix
1374 if (strcmp(s.ptr, "LOCK") == 0) { scdata.scan = SCAN_LOCK; return; } // LOCK prefix
1375 if (strcmp(s.ptr, "PTR") == 0) { scdata.scan = SCAN_PTR; return; } // PTR in MASM addressing statements
1376 if (strcmp(s.ptr, "CONST") == 0 || strcmp(s.ptr, "OFFSET") == 0) { scdata.scan = SCAN_OFS; return; } // Present but undefined offset/constant
1377 if (strcmp(s.ptr, "SIGNED") == 0) { scdata.scan = SCAN_SIGNED; return; } // Keyword "SIGNED" (in expressions)
1378 if (strcmp(s.ptr, "UNSIGNED") == 0) { scdata.scan = SCAN_UNSIGNED; return; } // Keyword "UNSIGNED" (in expressions)
1379 if (strcmp(s.ptr, "CHAR") == 0) { scdata.scan = SCAN_CHAR; return; } // Keyword "CHAR" (in expressions)
1380 if (strcmp(s.ptr, "FLOAT") == 0) { scdata.scan = SCAN_FLOAT; return; } // Keyword "FLOAT" (in expressions)
1381 if (strcmp(s.ptr, "DOUBLE") == 0) { scdata.scan = SCAN_DOUBLE; return; } // Keyword "DOUBLE" (in expressions)
1382 if (strcmp(s.ptr, "FLOAT10") == 0) { scdata.scan = SCAN_FLOAT10; return; } // Keyword "FLOAT10" (in expressions)
1383 if (strcmp(s.ptr, "STRING") == 0) { scdata.scan = SCAN_STRING; return; } // Keyword "STRING" (in expressions)
1384 if (strcmp(s.ptr, "UNICODE") == 0) { scdata.scan = SCAN_UNICODE; return; } // Keyword "UNICODE" (in expressions)
1385 if (strcmp(s.ptr, "MSG") == 0) { scdata.scan = SCAN_MSG; return; } // Pseudovariable MSG (in expressions)
1386 if (strcmp(s.ptr, "DEFB") == 0) { scdata.scan = SCAN_DEFB; return; }
1387 if (strcmp(s.ptr, "DEFW") == 0) { scdata.scan = SCAN_DEFW; return; }
1388 if (strcmp(s.ptr, "DEFD") == 0) { scdata.scan = SCAN_DEFD; return; }
1389 if (strcmp(s.ptr, "DB") == 0) { scdata.scan = SCAN_DEFB; return; }
1390 if (strcmp(s.ptr, "DW") == 0) { scdata.scan = SCAN_DEFW; return; }
1391 if (strcmp(s.ptr, "DD") == 0) { scdata.scan = SCAN_DEFD; return; }
1392 if (mode&SA_NAME) { scdata.idata = i; scdata.scan = SCAN_NAME; return; } // Don't try to decode symbolic label
1393 // symbol
1394 if (resolver !is null) {
1395 try {
1396 scdata.idata = resolver(symname);
1397 scdata.scan = SCAN_UCONST;
1398 scdata.skipBlanks();
1399 return;
1400 } catch (Exception) {}
1402 scdata.asmerror = "Unknown identifier";
1403 scdata.scan = SCAN_ERR;
1404 return;
1405 } else if (isdigit(*scdata.asmcmd)) {
1406 // Constant
1407 bool metHexDigit = false;
1408 auto saved = scdata.save;
1409 base = 0;
1410 maxdigit = 0;
1411 decimal = hex = 0;
1412 floating = 0;
1413 if (scdata.asmcmd[0] == '0' && toupper(scdata.asmcmd[1]) == 'X') { base = 16; scdata.asmcmd += 2; } // Force hexadecimal number
1414 for (;;) {
1415 if (isdigit(*scdata.asmcmd)) {
1416 decimal = decimal*10+(*scdata.asmcmd)-'0';
1417 floating = floating*10.0+(*scdata.asmcmd)-'0';
1418 hex = hex*16+(*scdata.asmcmd)-'0';
1419 if (maxdigit == 0) maxdigit = 9;
1420 ++scdata.asmcmd;
1421 } else if (isxdigit(*scdata.asmcmd)) {
1422 metHexDigit = true;
1423 hex = hex*16+toupper(*scdata.asmcmd++)-'A'+10;
1424 maxdigit = 15;
1425 } else {
1426 break;
1429 if (maxdigit == 0) {
1430 scdata.asmerror = "Hexadecimal digits after 0x... expected";
1431 scdata.scan = SCAN_ERR;
1432 return;
1434 if (toupper(*scdata.asmcmd) == 'H') {
1435 // Force hexadecimal number
1436 if (base == 16) {
1437 scdata.asmerror = "Please don't mix 0xXXXX and XXXXh forms";
1438 scdata.scan = SCAN_ERR;
1439 return;
1441 ++scdata.asmcmd;
1442 scdata.idata = hex;
1443 scdata.scan = SCAN_UCONST;
1444 if (!scdata.inMath && !scdata.noExprs) {
1445 // retreat and do expression
1446 scdata.inMath = true;
1447 scope(exit) scdata.inMath = false;
1448 scdata.restore(saved);
1449 doExpression();
1450 } else {
1451 scdata.skipBlanks();
1453 return;
1455 if (*scdata.asmcmd == '.') {
1456 // Force decimal number
1457 if (base == 16 || maxdigit > 9) { scdata.asmerror = "Not a decimal number"; scdata.scan = SCAN_ERR; return; }
1458 ++scdata.asmcmd;
1459 if (isdigit(*scdata.asmcmd) || toupper(*scdata.asmcmd) == 'E') {
1460 divisor = 1;
1461 // Floating-point number
1462 while (isdigit(*scdata.asmcmd)) {
1463 divisor /= 10.0;
1464 floating += divisor*(*scdata.asmcmd-'0');
1465 ++scdata.asmcmd;
1467 if (toupper(*scdata.asmcmd) == 'E') {
1468 ++scdata.asmcmd;
1469 if (*scdata.asmcmd == '-') { base = -1; scdata.asmcmd++; } else base = 1;
1470 if (!isdigit(*scdata.asmcmd)) { scdata.asmerror = "Invalid exponent"; scdata.scan = SCAN_ERR; return; }
1471 decimal = 0;
1472 while (isdigit(*scdata.asmcmd)) { if (decimal < 65536) decimal = decimal*10+(*scdata.asmcmd++)-'0'; }
1473 //floating *= pow10l(decimal*base);
1474 real dx = 1;
1475 if (base == -1) {
1476 while (decimal-- > 0) dx /= 10;
1477 } else {
1478 assert(base == 1);
1479 while (decimal-- > 0) dx *= 10;
1481 floating *= dx;
1483 scdata.fdata = floating;
1484 scdata.scan = SCAN_FCONST;
1485 if (!scdata.inMath && !scdata.noExprs) {
1486 // retreat and do expression
1487 scdata.inMath = true;
1488 scope(exit) scdata.inMath = false;
1489 scdata.restore(saved);
1490 doExpression();
1491 } else {
1492 scdata.skipBlanks();
1494 return;
1495 } else {
1496 scdata.fdata = decimal;
1497 scdata.scan = SCAN_FCONST;
1498 if (!scdata.inMath && !scdata.noExprs) {
1499 // retreat and do expression
1500 scdata.inMath = true;
1501 scope(exit) scdata.inMath = false;
1502 scdata.restore(saved);
1503 doExpression();
1504 } else {
1505 scdata.skipBlanks();
1507 return;
1510 // Default is hexadecimal
1511 if (scdata.defaultHex || metHexDigit || base == 16) {
1512 scdata.idata = hex;
1513 scdata.scan = SCAN_UCONST;
1514 } else {
1515 scdata.scan = SCAN_UCONST;
1516 scdata.idata = decimal;
1518 if (!scdata.inMath && !scdata.noExprs) {
1519 // retreat and do expression
1520 scdata.inMath = true;
1521 scope(exit) scdata.inMath = false;
1522 scdata.restore(saved);
1523 doExpression();
1524 } else {
1525 scdata.skipBlanks();
1527 return;
1528 } else if (*scdata.asmcmd == '$' && !isalnum(scdata.asmcmd[1])) {
1529 // dollar, current EIP
1530 auto saved = scdata.save;
1531 ++scdata.asmcmd;
1532 scdata.idata = scdata.stpc;
1533 scdata.scan = SCAN_UCONST;
1534 if (!scdata.inMath && !scdata.noExprs) {
1535 // retreat and do expression
1536 scdata.inMath = true;
1537 scope(exit) scdata.inMath = false;
1538 scdata.restore(saved);
1539 doExpression();
1540 } else {
1541 scdata.skipBlanks();
1543 return;
1544 } else if (*scdata.asmcmd == '\'' || *scdata.asmcmd == '`') {
1545 // Character constant
1546 char ech = *scdata.asmcmd++;
1547 char[4] cc;
1548 int ccpos = 0;
1549 foreach (immutable _; 0..4) {
1550 if (*scdata.asmcmd == '\0' || (*scdata.asmcmd == '\\' && scdata.asmcmd[1] == '\0')) { scdata.asmerror = "Unterminated character constant"; scdata.scan = SCAN_ERR; return; }
1551 if (*scdata.asmcmd == ech) {
1552 if (ccpos == 0) { scdata.asmerror = "Empty character constant"; scdata.scan = SCAN_ERR; return; }
1553 break;
1555 if (*scdata.asmcmd == '\\') {
1556 ++scdata.asmcmd;
1557 if (*scdata.asmcmd == '\0') { scdata.asmerror = "Unterminated character constant"; scdata.scan = SCAN_ERR; return; }
1558 switch (*scdata.asmcmd++) {
1559 case 't': cc[ccpos++] = '\t'; break;
1560 case 'r': cc[ccpos++] = '\r'; break;
1561 case 'n': cc[ccpos++] = '\n'; break;
1562 case 'x': case 'X':
1563 uint n = 0;
1564 if (!isxdigit(*scdata.asmcmd)) { scdata.asmerror = "Hex number expected"; scdata.scan = SCAN_ERR; return; }
1565 n = hdig(*scdata.asmcmd++);
1566 if (isxdigit(*scdata.asmcmd)) n = n*16+hdig(*scdata.asmcmd++);
1567 cc[ccpos++] = cast(char)n;
1568 break;
1569 default:
1570 if (isalpha(scdata.asmcmd[-1])) { scdata.asmerror = "Invalid escape"; scdata.scan = SCAN_ERR; return; }
1571 cc[ccpos++] = scdata.asmcmd[-1];
1572 break;
1574 } else {
1575 cc[ccpos++] = *scdata.asmcmd++;
1578 if (*scdata.asmcmd != ech) { scdata.asmerror = "Unterminated character constant"; scdata.scan = SCAN_ERR; return; }
1579 ++scdata.asmcmd;
1580 if (ccpos != 1 && ccpos != 2 && ccpos != 4) { scdata.asmerror = "Invalid character constant"; scdata.scan = SCAN_ERR; return; }
1581 if (ech == '`') {
1582 switch (ccpos) {
1583 case 1: scdata.idata = cast(ubyte)cc[0]; break;
1584 case 2: scdata.idata = ((cast(ubyte)cc[1])<<8)|(cast(ubyte)cc[0]); break;
1585 case 4: scdata.idata = ((cast(ubyte)cc[3])<<24)|((cast(ubyte)cc[2])<<16)|((cast(ubyte)cc[1])<<8)|(cast(ubyte)cc[0]); break;
1586 default: scdata.asmerror = "Invalid character constant"; scdata.scan = SCAN_ERR; return;
1588 } else {
1589 switch (ccpos) {
1590 case 1: scdata.idata = cast(ubyte)cc[0]; break;
1591 case 2: scdata.idata = ((cast(ubyte)cc[0])<<8)|(cast(ubyte)cc[1]); break;
1592 case 4: scdata.idata = ((cast(ubyte)cc[0])<<24)|((cast(ubyte)cc[1])<<16)|((cast(ubyte)cc[2])<<8)|(cast(ubyte)cc[3]); break;
1593 default: scdata.asmerror = "Invalid character constant"; scdata.scan = SCAN_ERR; return;
1596 scdata.skipBlanks();
1597 scdata.scan = SCAN_UCONST;
1598 return;
1599 } else {
1600 // Any other character or combination
1601 scdata.idata = scdata.sdata[0] = *scdata.asmcmd++;
1602 scdata.sdata[1] = scdata.sdata[2] = '\0';
1603 if (scdata.idata == '|' && *scdata.asmcmd == '|') { scdata.idata = S2toI!("||"); scdata.prio = 10; scdata.sdata[1] = *scdata.asmcmd++; }
1604 else if (scdata.idata == '&' && *scdata.asmcmd == '&') { scdata.idata = S2toI!("&&"); scdata.prio = 9; scdata.sdata[1] = *scdata.asmcmd++; }
1605 else if (scdata.idata == '=' && *scdata.asmcmd == '=') { scdata.idata = S2toI!("=="); scdata.prio = 5; scdata.sdata[1] = *scdata.asmcmd++; }
1606 else if (scdata.idata == '!' && *scdata.asmcmd == '=') { scdata.idata = S2toI!("!="); scdata.prio = 5; scdata.sdata[1] = *scdata.asmcmd++; }
1607 else if (scdata.idata == '<' && *scdata.asmcmd == '=') { scdata.idata = S2toI!("<="); scdata.prio = 4; scdata.sdata[1] = *scdata.asmcmd++; }
1608 else if (scdata.idata == '>' && *scdata.asmcmd == '=') { scdata.idata = S2toI!(">="); scdata.prio = 4; scdata.sdata[1] = *scdata.asmcmd++; }
1609 else if (scdata.idata == '<' && *scdata.asmcmd == '<') { scdata.idata = S2toI!("<<"); scdata.prio = 3; scdata.sdata[1] = *scdata.asmcmd++; }
1610 else if (scdata.idata == '>' && *scdata.asmcmd == '>') { scdata.idata = S2toI!(">>"); scdata.prio = 3; scdata.sdata[1] = *scdata.asmcmd++; }
1611 else if (scdata.idata == '|') scdata.prio = 8;
1612 else if (scdata.idata == '^') scdata.prio = 7;
1613 else if (scdata.idata == '&') scdata.prio = 6;
1614 else if (scdata.idata == '<') scdata.prio = 4;
1615 else if (scdata.idata == '>') scdata.prio = 4;
1616 else if (scdata.idata == '+') scdata.prio = 2;
1617 else if (scdata.idata == '-') scdata.prio = 2;
1618 else if (scdata.idata == '*') scdata.prio = 1;
1619 else if (scdata.idata == '/') scdata.prio = 1;
1620 else if (scdata.idata == '%') scdata.prio = 1;
1621 else if (scdata.idata == ']') {
1622 pcmd = scdata.asmcmd;
1623 scdata.skipBlanks();
1624 if (!scdata.inMath && *scdata.asmcmd == '[') {
1625 // Translate '][' to '+'
1626 scdata.idata = '+';
1627 scdata.prio = 2;
1628 ++scdata.asmcmd;
1629 } else {
1630 scdata.idata = ']';
1631 scdata.asmcmd = pcmd;
1632 scdata.prio = 0;
1634 } else {
1635 // Any other character
1636 scdata.prio = 0;
1638 scdata.scan = SCAN_SYMB;
1639 return;
1643 // Fetches one complete operand from the input line and fills in structure op
1644 // with operand's data. Expects that first token of the operand is already
1645 // scanned. Supports operands in generalized form (for example, R32 means any
1646 // of general-purpose 32-bit integer registers).
1647 private void Parseasmoperand (ref AsmScanData scdata, ref AsmOperand op, scope ResolveSymCB resolver) {
1648 int i, j, bracket, sign, xlataddr;
1649 int reg;
1650 int[9] r;
1651 int offset;
1652 if (scdata.scan == SCAN_EOL || scdata.scan == SCAN_ERR) return; // No or bad operand
1653 // Jump or call address may begin with address size modifier(s) SHORT, LONG,
1654 // NEAR and/or FAR. Not all combinations are allowed. After operand is
1655 // completely parsed, this function roughly checks whether modifier is
1656 // allowed. Exact check is done in Assemble().
1657 if (scdata.scan == SCAN_JMPSIZE) {
1658 j = 0;
1659 while (scdata.scan == SCAN_JMPSIZE) {
1660 // Fetch all size modifiers
1661 j |= scdata.idata;
1662 scanasm(scdata, 0, resolver);
1664 if (((j&0x03) == 0x03) || // Mixed SHORT and LONG
1665 ((j&0x0C) == 0x0C) || // Mixed NEAR and FAR
1666 ((j&0x09) == 0x09)) // Mixed FAR and SHORT
1668 scdata.asmerror = "Invalid combination of jump address modifiers";
1669 scdata.scan = SCAN_ERR;
1670 return;
1672 if ((j&0x08) == 0) j |= 0x04; // Force NEAR if not FAR
1673 op.jmpmode = j;
1675 // Simple operands are either register or constant, their processing is
1676 // obvious and straightforward.
1677 if (scdata.scan == SCAN_REG8 || scdata.scan == SCAN_REG16 || scdata.scan == SCAN_REG32) {
1678 // Integer general-purpose register
1679 op.type = REG;
1680 op.index = scdata.idata;
1681 if (scdata.scan == SCAN_REG8) op.size = 1;
1682 else if (scdata.scan == SCAN_REG16) op.size = 2;
1683 else op.size = 4;
1684 } else if (scdata.scan == SCAN_FPU) {
1685 // FPU register
1686 op.type = RST;
1687 op.index = scdata.idata;
1688 } else if (scdata.scan == SCAN_MMX) {
1689 // MMX or 3DNow! register
1690 op.type = RMX;
1691 op.index = scdata.idata;
1692 } else if (scdata.scan == SCAN_CR) {
1693 // Control register
1694 op.type = CRX;
1695 op.index = scdata.idata;
1696 } else if (scdata.scan == SCAN_DR) {
1697 // Debug register
1698 op.type = DRX;
1699 op.index = scdata.idata;
1700 } else if (scdata.scan == SCAN_SYMB && scdata.idata == '-') {
1701 // Negative constant
1702 scanasm(scdata, 0, resolver);
1703 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST && scdata.scan != SCAN_OFS) {
1704 scdata.asmerror = "Integer number expected";
1705 scdata.scan = SCAN_ERR;
1706 return;
1708 op.type = IMM;
1709 op.offset = -scdata.idata;
1710 if (scdata.scan == SCAN_OFS) op.anyoffset = 1;
1711 } else if (scdata.scan == SCAN_SYMB && scdata.idata == '+') {
1712 // Positive constant
1713 scanasm(scdata, 0, resolver);
1714 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST && scdata.scan != SCAN_OFS) {
1715 scdata.asmerror = "Integer number expected";
1716 scdata.scan = SCAN_ERR;
1717 return;
1719 op.type = IMM;
1720 op.offset = scdata.idata;
1721 if (scdata.scan == SCAN_OFS) op.anyoffset = 1;
1722 } else if (scdata.scan == SCAN_UCONST || scdata.scan == SCAN_DCONST || scdata.scan == SCAN_OFS) {
1723 j = scdata.idata;
1724 if (scdata.scan == SCAN_OFS) op.anyoffset = 1;
1725 scanasm(scdata, 0, resolver);
1726 if (scdata.scan == SCAN_SYMB && scdata.idata == ':') {
1727 // Absolute long address (seg:offset)
1728 scanasm(scdata, 0, resolver);
1729 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST && scdata.scan != SCAN_OFS) {
1730 scdata.asmerror = "Integer address expected";
1731 scdata.scan = SCAN_ERR;
1732 return;
1734 op.type = JMF;
1735 op.offset = scdata.idata;
1736 op.segment = j;
1737 if (scdata.scan == SCAN_OFS) op.anyoffset = 1;
1738 } else {
1739 // Constant without sign
1740 op.type = IMM;
1741 op.offset = j;
1742 return; // Next token already scanned
1744 } else if (scdata.scan == SCAN_FCONST) {
1745 scdata.asmerror = "Floating-point numbers are not allowed in command";
1746 scdata.scan = SCAN_ERR;
1747 return;
1748 } else if (scdata.scan == SCAN_SEG || scdata.scan == SCAN_OPSIZE || (scdata.scan == SCAN_SYMB && scdata.idata == '[')) {
1749 // Segment register or address
1750 bracket = 0;
1751 if (scdata.scan == SCAN_SEG) {
1752 j = scdata.idata;
1753 scanasm(scdata, 0, resolver);
1754 if (scdata.scan != SCAN_SYMB || scdata.idata != ':') {
1755 // Segment register as operand
1756 op.type = SGM;
1757 op.index = j;
1758 return; // Next token already scanned
1760 op.segment = j;
1761 scanasm(scdata, 0, resolver);
1763 // Scan 32-bit address. This parser does not support 16-bit addresses.
1764 // First of all, get size of operand (optional), segment register (optional)
1765 // and opening bracket (required).
1766 for (;;) {
1767 if (scdata.scan == SCAN_SYMB && scdata.idata == '[') {
1768 // Bracket
1769 if (bracket) { scdata.asmerror = "Only one opening bracket allowed"; scdata.scan = SCAN_ERR; return; }
1770 bracket = 1;
1771 } else if (scdata.scan == SCAN_OPSIZE) {
1772 // Size of operand
1773 if (op.size != 0) { scdata.asmerror = "Duplicated size modifier"; scdata.scan = SCAN_ERR; return; }
1774 op.size = scdata.idata;
1775 } else if (scdata.scan == SCAN_SEG) {
1776 // Segment register
1777 if (op.segment != SEG_UNDEF) { scdata.asmerror = "Duplicated segment register"; scdata.scan = SCAN_ERR; return; }
1778 op.segment = scdata.idata;
1779 scanasm(scdata, 0, resolver);
1780 if (scdata.scan != SCAN_SYMB || scdata.idata != ':') { scdata.asmerror = "Semicolon expected"; scdata.scan = SCAN_ERR; return; }
1781 } else if (scdata.scan == SCAN_ERR) {
1782 return;
1783 } else {
1784 // None of expected address elements
1785 break;
1787 scanasm(scdata, 0, resolver);
1789 if (bracket == 0) { scdata.asmerror = "Address expression requires brackets"; scdata.scan = SCAN_ERR; return; }
1790 // Assembling a 32-bit address may be a kind of nigthmare, due to a large
1791 // number of allowed forms. Parser collects immediate offset in op.offset
1792 // and count for each register in array r[]. Then it decides whether this
1793 // combination is valid and determines scale, index and base. Assemble()
1794 // will use these numbers to select address form (with or without SIB byte,
1795 // 8- or 32-bit offset, use segment prefix or not). As a useful side effect
1796 // of this technique, one may specify, for example, [EAX*5] which will
1797 // correctly assemble to [EAX*4+EAX].
1798 //for (i = 0; i <= 8; ++i) r[i] = 0;
1799 r[] = 0;
1800 sign = '+'; // Default sign for the first operand
1801 xlataddr = 0;
1802 // Get SIB and offset
1803 for (;;) {
1804 if (scdata.scan == SCAN_SYMB && (scdata.idata == '+' || scdata.idata == '-')) {
1805 sign = scdata.idata;
1806 scanasm(scdata, 0, resolver);
1808 if (scdata.scan == SCAN_ERR) return;
1809 if (sign == '?') { scdata.asmerror = "Syntax error (1)"; scdata.scan = SCAN_ERR; return; }
1810 // Register AL appears as part of operand of (seldom used) command XLAT.
1811 if (scdata.scan == SCAN_REG8 && scdata.idata == REG_EAX) {
1812 if (sign == '-') { scdata.asmerror = "Unable to subtract register"; scdata.scan = SCAN_ERR; return; }
1813 if (xlataddr != 0) { scdata.asmerror = "Too many registers"; scdata.scan = SCAN_ERR; return; }
1814 xlataddr = 1;
1815 scanasm(scdata, 0, resolver);
1816 } else if (scdata.scan == SCAN_REG16) {
1817 scdata.asmerror = "Sorry, 16-bit addressing is not supported";
1818 scdata.scan = SCAN_ERR;
1819 return;
1820 } else if (scdata.scan == SCAN_REG32) {
1821 if (sign == '-') { scdata.asmerror = "Unable to subtract register"; scdata.scan = SCAN_ERR; return; }
1822 reg = scdata.idata;
1823 scanasm(scdata, 0, resolver);
1824 if (scdata.scan == SCAN_SYMB && scdata.idata == '*') {
1825 // Try index*scale
1826 scanasm(scdata, 0, resolver);
1827 if (scdata.scan == SCAN_ERR) return;
1828 if (scdata.scan == SCAN_OFS) { scdata.asmerror = "Undefined scale is not allowed"; scdata.scan = SCAN_ERR; return; }
1829 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST) { scdata.asmerror = "Syntax error (2)"; scdata.scan = SCAN_ERR; return; }
1830 if (scdata.idata == 6 || scdata.idata == 7 || scdata.idata > 9) { scdata.asmerror = "Invalid scale"; scdata.scan = SCAN_ERR; return; }
1831 r[reg] += scdata.idata;
1832 scanasm(scdata, 0, resolver);
1833 } else {
1834 // Simple register
1835 ++r[reg];
1837 } else if (scdata.scan == SCAN_LOCAL) {
1838 ++r[REG_EBP];
1839 op.offset -= scdata.idata*4;
1840 scanasm(scdata, 0, resolver);
1841 } else if (scdata.scan == SCAN_ARG) {
1842 ++r[REG_EBP];
1843 op.offset += (scdata.idata+1)*4;
1844 scanasm(scdata, 0, resolver);
1845 } else if (scdata.scan == SCAN_UCONST || scdata.scan == SCAN_DCONST) {
1846 offset = scdata.idata;
1847 scanasm(scdata, 0, resolver);
1848 if (scdata.scan == SCAN_SYMB && scdata.idata == '*') {
1849 // Try scale*index
1850 scanasm(scdata, 0, resolver);
1851 if (scdata.scan == SCAN_ERR) return;
1852 if (sign == '-') { scdata.asmerror = "Unable to subtract register"; scdata.scan = SCAN_ERR; return; }
1853 if (scdata.scan == SCAN_REG16) { scdata.asmerror = "Sorry, 16-bit addressing is not supported"; scdata.scan = SCAN_ERR; return; }
1854 if (scdata.scan != SCAN_REG32) { scdata.asmerror = "Syntax error (3)"; scdata.scan = SCAN_ERR; return; }
1855 if (offset == 6 || offset == 7 || offset > 9) { scdata.asmerror = "Invalid scale"; scdata.scan = SCAN_ERR; return; }
1856 r[scdata.idata] += offset;
1857 scanasm(scdata, 0, resolver);
1858 } else {
1859 if (sign == '-') op.offset -= offset; else op.offset += offset;
1861 } else if (scdata.scan == SCAN_OFS) {
1862 scanasm(scdata, 0, resolver);
1863 if (scdata.scan == SCAN_SYMB && scdata.idata == '*') { scdata.asmerror = "Undefined scale is not allowed"; scdata.scan = SCAN_ERR; return; }
1864 op.anyoffset = 1;
1865 } else {
1866 // None of expected address elements
1867 break;
1869 if (scdata.scan == SCAN_SYMB && scdata.idata == ']') break;
1870 sign = '?';
1872 if (scdata.scan == SCAN_ERR) return;
1873 if (scdata.scan != SCAN_SYMB || scdata.idata != ']') { scdata.asmerror = "Syntax error (4)"; scdata.scan = SCAN_ERR; return; }
1874 // Process XLAT address separately.
1875 if (xlataddr != 0) {
1876 // XLAT address in form [EBX+AX]
1877 // Check which registers used
1878 for (i = 0; i <= 8; ++i) {
1879 if (i == REG_EBX) continue;
1880 if (r[i] != 0) break;
1882 if (i <= 8 || r[REG_EBX] != 1 || op.offset != 0 || op.anyoffset != 0) { scdata.asmerror = "Invalid address"; scdata.scan = SCAN_ERR; return; }
1883 op.type = MXL;
1884 } else {
1885 // Determine scale, index and base.
1886 j = 0; // Number of used registers
1887 for (i = 0; i <= 8; ++i) {
1888 if (r[i] == 0) continue; // Unused register
1889 if (r[i] == 3 || r[i] == 5 || r[i] == 9) {
1890 if (op.index >= 0 || op.base >= 0) { scdata.asmerror = (j == 0 ? "Invalid scale" : "Too many registers"); scdata.scan = SCAN_ERR; return; }
1891 op.index = op.base = i;
1892 op.scale = r[i]-1;
1893 } else if (r[i] == 2 || r[i] == 4 || r[i] == 8) {
1894 if (op.index >= 0) { scdata.asmerror = (j <= 1 ? "Only one register may be scaled" : "Too many registers"); scdata.scan = SCAN_ERR; return; }
1895 op.index = i;
1896 op.scale = r[i];
1897 } else if (r[i] == 1) {
1898 if (op.base < 0) op.base = i;
1899 else if (op.index < 0) { op.index = i; op.scale = 1; }
1900 else { scdata.asmerror = "Too many registers"; scdata.scan = SCAN_ERR; return; }
1901 } else {
1902 scdata.asmerror = "Invalid scale";
1903 scdata.scan = SCAN_ERR;
1904 return;
1906 ++j;
1908 op.type = MRG;
1910 } else {
1911 scdata.asmerror = "Unrecognized operand";
1912 scdata.scan = SCAN_ERR;
1913 return;
1915 // In general, address modifier is allowed only with address expression which
1916 // is a constant, a far address or a memory expression. More precise check
1917 // will be done later in Assemble().
1918 if (op.jmpmode != 0 && op.type != IMM && op.type != JMF && op.type != MRG) {
1919 scdata.asmerror = "Jump address modifier is not allowed";
1920 scdata.scan = SCAN_ERR;
1921 return;
1923 scanasm(scdata, 0, resolver); // Fetch next token from input line
1927 /** Parse and assemble x86 instruction.
1929 * This function assembles text into 32-bit 80x86 machine code. It supports imprecise
1930 * operands (for example, R32 stays for any general-purpose 32-bit register).
1931 * This allows to search for incomplete commands. Command is precise when all
1932 * significant bytes in model.mask are 0xFF. Some commands have more than one
1933 * decoding. By calling Assemble() with attempt=0, 1... and constsize=0, 1, 2, 3
1934 * one gets also alternative variants (bit 0x1 of constsize is responsible for
1935 * size of address constant and bit 0x2 - for immediate data). However, only one
1936 * address form is generated ([EAX*2], but not [EAX+EAX]; [EBX+EAX] but not
1937 * [EAX+EBX]; [EAX] will not use SIB byte; no DS: prefix and so on).
1939 * Returns number of bytes in assembled code or non-positive number in case of
1940 * detected error. This number is the negation of the offset in the input text
1941 * where the error encountered.
1943 public int assemble(const(char)[] cmdstr, uint ip, AsmModel* model, in AsmOptions opts, uint attempt, uint constsize, char[] errtext,
1944 scope ResolveSymCB resolver=null,
1945 scope PutDataCB putdata=null)
1947 import core.stdc.ctype : isalpha, isalnum, isdigit, toupper, isxdigit;
1948 import core.stdc.stdio : snprintf;
1949 import core.stdc.string : memcpy, memset, strcpy, strcmp, strlen;
1950 int i, j, k, namelen, nameok, arg, match, datasize, addrsize, bytesize, minop, maxop;
1951 int rep, lock, segment, jmpsize, jmpmode, longjump;
1952 int hasrm, hassib, dispsize, immsize;
1953 int anydisp, anyimm, anyjmp;
1954 int l, displacement, immediate, jmpoffset;
1955 char[32] name = 0;
1956 const(char)* nameend;
1957 ubyte[ASMMAXCMDSIZE] tcode;
1958 ubyte[ASMMAXCMDSIZE] tmask;
1959 AsmOperand[3] aop; // Up to 3 operands allowed
1960 AsmOperand* op;
1961 immutable(AsmInstrData)* pd;
1962 AsmScanData scdata;
1964 if (model !is null) model.length = 0;
1965 if (model is null || cmdstr.length > scdata.acommand.length-1) {
1966 // Error in parameters
1967 if (errtext !is null) xstrcpy(errtext, "Internal OLLYASM error");
1968 return 0;
1970 model.data = false;
1971 scdata.acommand[] = 0;
1972 scdata.acommand[0..cmdstr.length] = cmdstr;
1973 scdata.asmcmd = scdata.acommand.ptr;
1974 scdata.stpc = ip;
1975 rep = lock = 0;
1976 errtext[0] = '\0';
1977 scanasm(scdata, SA_NAME, resolver);
1978 if (scdata.scan == SCAN_EOL) return 0; // End of line, nothing to assemble
1980 // process "db" and company
1981 if (scdata.scan == SCAN_DEFB || scdata.scan == SCAN_DEFW || scdata.scan == SCAN_DEFD) {
1982 if (attempt != 0) { xstrcpy(errtext, "Invalid command"); goto error; } // only one attempt
1983 uint bpos = 0;
1984 model.length = 0;
1985 model.jmpsize = 0;
1986 model.jmpoffset = 0;
1987 model.jmppos = 0;
1988 model.data = true;
1989 int csize = (scdata.scan == SCAN_DEFB ? 1 : scdata.scan == SCAN_DEFW ? 2 : 4);
1991 bool dbPutByte (ubyte vb) {
1992 if (putdata !is null) {
1993 if (bpos < model.code.length) {
1994 model.code[bpos] = vb;
1995 model.mask[bpos] = 0xff;
1996 ++bpos;
1998 putdata(ip+model.length, vb);
1999 } else {
2000 if (bpos >= model.code.length) { xstrcpy(errtext, "too many byte constants"); return false; }
2001 model.code[bpos] = vb;
2002 model.mask[bpos] = 0xff;
2003 ++bpos;
2005 ++model.length;
2006 return true;
2009 bool dbPutConst (uint v) {
2010 foreach (immutable _; 0..csize) {
2011 if (!dbPutByte(v&0xff)) return false;
2012 v >>= 8;
2014 return true;
2017 for (;;) {
2018 scanasm(scdata, 0, resolver);
2019 if (scdata.scan == SCAN_ERR) { xstrcpyx(errtext, scdata.asmerror); goto error; }
2020 if (scdata.scan == SCAN_EOL) {
2021 if (bpos == 0) { xstrcpy(errtext, "byte constant expected"); goto error; }
2022 break;
2024 if (bpos != 0) {
2025 if (scdata.scan != SCAN_SYMB || scdata.idata != ',') { xstrcpy(errtext, "comma expected"); goto error; }
2026 scanasm(scdata, 0, resolver);
2027 if (scdata.scan == SCAN_ERR) { xstrcpyx(errtext, scdata.asmerror); goto error; }
2029 if (scdata.scan == SCAN_SYMB && scdata.idata == '"') {
2030 // parse string
2031 while (*scdata.asmcmd && *scdata.asmcmd != '"') {
2032 ubyte vb;
2033 if (*scdata.asmcmd != '\\') {
2034 vb = cast(ubyte)(*scdata.asmcmd++);
2035 } else {
2036 ++scdata.asmcmd;
2037 switch (*scdata.asmcmd++) {
2038 case 0: xstrcpy(errtext, "Unexpected end of string"); goto error;
2039 case 't': vb = cast(ubyte)'\t'; break;
2040 case 'r': vb = cast(ubyte)'\r'; break;
2041 case 'n': vb = cast(ubyte)'\n'; break;
2042 case 'x': case 'X':
2043 uint n = 0;
2044 if (!isxdigit(*scdata.asmcmd)) { xstrcpy(errtext, "Hex number expected"); goto error; }
2045 n = hdig(*scdata.asmcmd++);
2046 if (isxdigit(*scdata.asmcmd)) n = n*16+hdig(*scdata.asmcmd++);
2047 vb = cast(char)n;
2048 break;
2049 default:
2050 if (isalpha(scdata.asmcmd[-1])) { xstrcpy(errtext, "Invalid escape"); goto error; }
2051 vb = cast(ubyte)scdata.asmcmd[-1];
2052 break;
2055 if (!dbPutByte(vb)) goto error;
2057 if (*scdata.asmcmd == '"') ++scdata.asmcmd;
2058 } else {
2059 if (scdata.scan != SCAN_UCONST && scdata.scan != SCAN_DCONST) { xstrcpy(errtext, "constant expected"); goto error; }
2060 final switch (csize) {
2061 case 1: if (scdata.idata < byte.min || scdata.idata > ubyte.max) { xstrcpy(errtext, "byte constant overflow"); goto error; } break;
2062 case 2: if (scdata.idata < short.min || scdata.idata > ushort.max) { xstrcpy(errtext, "word constant overflow"); goto error; } break;
2063 case 4: break;
2065 //{ import core.stdc.stdio; printf("DB: 0x%02x\n", cast(ubyte)(scdata.idata&0xff)); }
2066 if (!dbPutConst(scdata.idata)) goto error;
2069 return model.length;
2072 //scdata.noExprs = true; // temp
2073 // Fetch all REPxx and LOCK prefixes
2074 for (;;) {
2075 if (scdata.scan == SCAN_REP || scdata.scan == SCAN_REPE || scdata.scan == SCAN_REPNE) {
2076 if (rep != 0) { xstrcpy(errtext, "Duplicated REP prefix"); goto error; }
2077 rep = scdata.scan;
2078 } else if (scdata.scan == SCAN_LOCK) {
2079 if (lock != 0) { xstrcpy(errtext, "Duplicated LOCK prefix"); goto error; }
2080 lock = scdata.scan;
2081 } else {
2082 // No more prefixes
2083 break;
2085 scanasm(scdata, SA_NAME, resolver);
2087 if (scdata.scan != SCAN_NAME || scdata.idata > 16 || toupper(scdata.sdata[0]) < 'A' || toupper(scdata.sdata[0]) > 'Z') { xstrcpy(errtext, "Command mnemonic expected"); goto error; }
2088 nameend = scdata.asmcmd;
2089 strupr(scdata.sdata.ptr);
2090 // Prepare full mnemonic (including repeat prefix, if any).
2091 if (rep == SCAN_REP) snprintf(name.ptr, name.length, "REP %s", scdata.sdata.ptr);
2092 else if (rep == SCAN_REPE) snprintf(name.ptr, name.length, "REPE %s", scdata.sdata.ptr);
2093 else if (rep == SCAN_REPNE) snprintf(name.ptr, name.length, "REPNE %s", scdata.sdata.ptr);
2094 else strcpy(name.ptr, scdata.sdata.ptr);
2095 scanasm(scdata, 0, resolver);
2096 // Parse command operands (up to 3). Note: jump address is always the first
2097 // (and only) operand in actual command set.
2098 for (i = 0; i < 3; ++i) {
2099 aop[i].type = NNN; // No operand
2100 aop[i].size = 0; // Undefined size
2101 aop[i].index = -1; // No index
2102 aop[i].scale = 0; // No scale
2103 aop[i].base = -1; // No base
2104 aop[i].offset = 0; // No offset
2105 aop[i].anyoffset = 0; // No offset
2106 aop[i].segment = SEG_UNDEF; // No segment
2107 aop[i].jmpmode = 0; // No jump size modifier
2109 Parseasmoperand(scdata, aop[0], resolver);
2110 jmpmode = aop[0].jmpmode;
2111 if (jmpmode != 0) jmpmode |= 0x80;
2112 if (scdata.scan == SCAN_SYMB && scdata.idata == ',') {
2113 scanasm(scdata, 0, resolver);
2114 Parseasmoperand(scdata, aop[1], resolver);
2115 if (scdata.scan == SCAN_SYMB && scdata.idata == ',') {
2116 scanasm(scdata, 0, resolver);
2117 Parseasmoperand(scdata, aop[2], resolver);
2120 if (scdata.scan == SCAN_ERR) { xstrcpyx(errtext, scdata.asmerror); goto error; }
2121 if (scdata.scan != SCAN_EOL) { xstrcpy(errtext, "Extra input after operand"); goto error; }
2122 // If jump size is not specified, function tries to use short jump. If
2123 // attempt fails, it retries with long form.
2124 longjump = 0; // Try short jump on the first pass
2125 retrylongjump:
2126 nameok = 0;
2127 // Some commands allow different number of operands. Variables minop and
2128 // maxop accumulate their minimal and maximal counts. The numbers are not
2129 // used in assembly process but allow for better error diagnostics.
2130 minop = 3;
2131 maxop = 0;
2132 // Main assembly loop: try to find the command which matches all operands,
2133 // but do not process operands yet.
2134 namelen = strlen(name.ptr);
2135 if (toupper(name[0]) < 'A' || toupper(name[0] > 'Z')) assert(0, "internal assembler error");
2136 foreach (uint amnidx; asmmnemolist[toupper(name[0])-'A'][]) {
2137 if (amnidx == uint.max) break;
2138 pd = &asmInstrs[amnidx];
2139 if (pd.name[0] == '&') {
2140 // Mnemonic depends on operand size
2141 j = 1;
2142 datasize = 2;
2143 addrsize = 4;
2144 // Try all mnemonics (separated by ':')
2145 for (;;) {
2146 for (i = 0; pd.name[j] != '\0' && pd.name[j] != ':'; ++j) {
2147 if (pd.name[j] == '*') {
2148 if (name[i] == 'W') { datasize = 2; ++i; }
2149 else if (name[i] == 'D') { datasize = 4; ++i; }
2150 else if (!opts.sizesens) datasize = 2;
2151 else datasize = 4;
2152 } else if (pd.name[j] == name[i]) {
2153 ++i;
2154 } else {
2155 break;
2158 if (name[i] == '\0' && (pd.name[j] == '\0' || pd.name[j] == ':')) break; // Bingo!
2159 while (pd.name[j] != '\0' && pd.name[j] != ':') ++j;
2160 if (pd.name[j] == ':') {
2161 // Retry with 32-bit mnenonic
2162 ++j;
2163 datasize = 4;
2164 } else {
2165 // Comparison failed
2166 i = 0;
2167 break;
2170 if (i == 0) continue;
2171 } else if (pd.name[0] == '$') {
2172 // Mnemonic depends on address size
2173 j = 1;
2174 datasize = 0;
2175 addrsize = 2;
2176 // Try all mnemonics (separated by ':')
2177 for (;;) {
2178 for (i = 0; pd.name[j] != '\0' && pd.name[j] != ':'; ++j) {
2179 if (pd.name[j] == '*') {
2180 if (name[i] == 'W') { addrsize = 2; ++i; }
2181 else if (name[i] == 'D') { addrsize = 4; ++i; }
2182 else if (!opts.sizesens) addrsize = 2;
2183 else addrsize = 4;
2184 } else if (pd.name[j] == name[i]) {
2185 ++i;
2186 } else {
2187 break;
2190 if (name[i] == '\0' && (pd.name[j] == '\0' || pd.name[j] == ':')) break; // Bingo!
2191 while (pd.name[j] != '\0' && pd.name[j] != ':') ++j;
2192 if (pd.name[j] == ':') {
2193 // Retry with 32-bit mnenonic
2194 ++j;
2195 addrsize = 4;
2196 } else {
2197 // Comparison failed
2198 i = 0;
2199 break;
2202 if (i == 0) continue;
2203 } else {
2204 // Compare with all synonimes
2205 j = k = 0;
2206 datasize = 0; // Default settings
2207 addrsize = 4;
2208 for (;;) {
2209 while (j < pd.name.length && pd.name[j] != ',' && pd.name[j] != '\0') ++j;
2210 if (j-k == namelen && strnicmp(name.ptr, pd.name.ptr+k, namelen) == 0) break;
2211 k = j+1;
2212 if (j >= pd.name.length || pd.name[j] == '\0') break;
2213 j = k;
2215 if (k > j) continue;
2217 // For error diagnostics it is important to know whether mnemonic exists.
2218 ++nameok;
2219 if (pd.arg1 == NNN || pd.arg1 >= PSEUDOOP) {
2220 minop = 0;
2221 } else if (pd.arg2 == NNN || pd.arg2 >= PSEUDOOP) {
2222 if (minop > 1) minop = 1;
2223 if (maxop < 1) maxop = 1;
2224 } else if (pd.arg3 == NNN || pd.arg3 >= PSEUDOOP) {
2225 if (minop > 2) minop = 2;
2226 if (maxop < 2) maxop = 2;
2227 } else {
2228 maxop = 3;
2230 // Determine default and allowed operand size(s).
2231 if (pd.bits == FF) datasize = 2; // Forced 16-bit size
2232 bytesize = (pd.bits == WW || pd.bits == WS || pd.bits == W3 || pd.bits == WP ? 1 : 0); // 1-byte size allowed or Word/dword size only
2233 // Check whether command operands match specified. If so, variable match
2234 // remains zero, otherwise it contains kind of mismatch. This allows for
2235 // better error diagnostics.
2236 match = 0;
2237 // Up to 3 operands
2238 for (j = 0; j < 3; ++j) {
2239 op = aop.ptr+j;
2240 if (j == 0) arg = pd.arg1;
2241 else if (j == 1) arg = pd.arg2;
2242 else arg = pd.arg3;
2243 if (arg == NNN || arg >= PSEUDOOP) {
2244 if (op.type != NNN) match |= MA_NOP; // No more arguments
2245 break;
2247 if (op.type == NNN) { match |= MA_NOP; break; } // No corresponding operand
2248 switch (arg) {
2249 case REG: // Integer register in Reg field
2250 case RCM: // Integer register in command byte
2251 case RAC: // Accumulator (AL/AX/EAX, implicit)
2252 if (op.type != REG) match |= MA_TYP;
2253 if (arg == RAC && op.index != REG_EAX && op.index != 8) match |= MA_TYP;
2254 if (bytesize == 0 && op.size == 1) match |= MA_SIZ;
2255 if (datasize == 0) datasize = op.size;
2256 if (datasize != op.size) match |= MA_DIF;
2257 break;
2258 case RG4: // Integer 4-byte register in Reg field
2259 if (op.type != REG) match |= MA_TYP;
2260 if (op.size != 4) match |= MA_SIZ;
2261 if (datasize == 0) datasize = op.size;
2262 if (datasize != op.size) match |= MA_DIF;
2263 break;
2264 case RAX: // AX (2-byte, implicit)
2265 if (op.type != REG || (op.index != REG_EAX && op.index != 8)) match |= MA_TYP;
2266 if (op.size != 2) match |= MA_SIZ;
2267 if (datasize == 0) datasize = op.size;
2268 if (datasize != op.size) match |= MA_DIF;
2269 break;
2270 case RDX: // DX (16-bit implicit port address)
2271 if (op.type != REG || (op.index != REG_EDX && op.index != 8)) match |= MA_TYP;
2272 if (op.size != 2) match |= MA_SIZ; break;
2273 case RCL: // Implicit CL register (for shifts)
2274 if (op.type != REG || (op.index != REG_ECX && op.index != 8)) match |= MA_TYP;
2275 if (op.size != 1) match |= MA_SIZ;
2276 break;
2277 case RS0: // Top of FPU stack (ST(0))
2278 if (op.type != RST || (op.index != 0 && op.index != 8)) match |= MA_TYP;
2279 break;
2280 case RST: // FPU register (ST(i)) in command byte
2281 if (op.type != RST) match |= MA_TYP;
2282 break;
2283 case RMX: // MMX register MMx
2284 case R3D: // 3DNow! register MMx
2285 if (op.type != RMX) match |= MA_TYP;
2286 break;
2287 case MRG: // Memory/register in ModRM byte
2288 if (op.type != MRG && op.type != REG) match |= MA_TYP;
2289 if (bytesize == 0 && op.size == 1) match |= MA_SIZ;
2290 if (datasize == 0) datasize = op.size;
2291 if (op.size != 0 && op.size != datasize) match |= MA_DIF;
2292 break;
2293 case MR1: // 1-byte memory/register in ModRM byte
2294 if (op.type != MRG && op.type != REG) match |= MA_TYP;
2295 if (op.size != 0 && op.size != 1) match |= MA_SIZ;
2296 break;
2297 case MR2: // 2-byte memory/register in ModRM byte
2298 if (op.type != MRG && op.type != REG) match |= MA_TYP;
2299 if (op.size != 0 && op.size != 2) match |= MA_SIZ;
2300 break;
2301 case MR4: // 4-byte memory/register in ModRM byte
2302 if (op.type != MRG && op.type != REG) match |= MA_TYP;
2303 if (op.size != 0 && op.size != 4) match |= MA_SIZ;
2304 break;
2305 case RR4: // 4-byte memory/register (register only)
2306 if (op.type != REG) match |= MA_TYP;
2307 if (op.size != 0 && op.size != 4) match |= MA_SIZ;
2308 break;
2309 case MRJ: // Memory/reg in ModRM as JUMP target
2310 if (op.type != MRG && op.type != REG) match |= MA_TYP;
2311 if (op.size != 0 && op.size != 4) match |= MA_SIZ;
2312 if ((jmpmode&0x09) != 0) match |= MA_JMP;
2313 jmpmode &= 0x7F;
2314 break;
2315 case MR8: // 8-byte memory/MMX register in ModRM
2316 case MRD: // 8-byte memory/3DNow! register in ModRM
2317 if (op.type != MRG && op.type != RMX) match |= MA_TYP;
2318 if (op.size != 0 && op.size != 8) match |= MA_SIZ;
2319 break;
2320 case RR8: // 8-byte MMX register only in ModRM
2321 case RRD: // 8-byte memory/3DNow! (register only)
2322 if (op.type != RMX) match |= MA_TYP;
2323 if (op.size != 0 && op.size != 8) match |= MA_SIZ;
2324 break;
2325 case MMA: // Memory address in ModRM byte for LEA
2326 if (op.type != MRG) match |= MA_TYP; break;
2327 case MML: // Memory in ModRM byte (for LES)
2328 if (op.type != MRG) match |= MA_TYP;
2329 if (op.size != 0 && op.size != 6) match |= MA_SIZ;
2330 if (datasize == 0) datasize = 4; else if (datasize != 4) match |= MA_DIF;
2331 break;
2332 case MMS: // Memory in ModRM byte (as SEG:OFFS)
2333 if (op.type != MRG) match |= MA_TYP;
2334 if (op.size != 0 && op.size != 6) match |= MA_SIZ;
2335 if ((jmpmode&0x07) != 0) match |= MA_JMP;
2336 jmpmode &= 0x7F;
2337 break;
2338 case MM6: // Memory in ModRm (6-byte descriptor)
2339 if (op.type != MRG) match |= MA_TYP;
2340 if (op.size != 0 && op.size != 6) match |= MA_SIZ;
2341 break;
2342 case MMB: // Two adjacent memory locations (BOUND)
2343 if (op.type != MRG) match |= MA_TYP;
2344 k = op.size; if (opts.ideal == 0 && k > 1) k /= 2;
2345 if (k != 0 && k != datasize) match |= MA_DIF;
2346 break;
2347 case MD2: // Memory in ModRM byte (16-bit integer)
2348 case MB2: // Memory in ModRM byte (16-bit binary)
2349 if (op.type != MRG) match |= MA_TYP;
2350 if (op.size != 0 && op.size != 2) match |= MA_SIZ;
2351 break;
2352 case MD4: // Memory in ModRM byte (32-bit integer)
2353 case MF4: // Memory in ModRM byte (32-bit float)
2354 if (op.type != MRG) match |= MA_TYP;
2355 if (op.size != 0 && op.size != 4) match |= MA_SIZ;
2356 break;
2357 case MD8: // Memory in ModRM byte (64-bit integer)
2358 case MF8: // Memory in ModRM byte (64-bit float)
2359 if (op.type != MRG) match |= MA_TYP;
2360 if (op.size != 0 && op.size != 8) match |= MA_SIZ;
2361 break;
2362 case MDA: // Memory in ModRM byte (80-bit BCD)
2363 case MFA: // Memory in ModRM byte (80-bit float)
2364 if (op.type != MRG) match |= MA_TYP;
2365 if (op.size != 0 && op.size != 10) match |= MA_SIZ;
2366 break;
2367 case MFE: // Memory in ModRM byte (FPU environment)
2368 case MFS: // Memory in ModRM byte (FPU state)
2369 case MFX: // Memory in ModRM byte (ext. FPU state)
2370 if (op.type != MRG) match |= MA_TYP;
2371 if (op.size != 0) match |= MA_SIZ;
2372 break;
2373 case MSO: // Source in string operands ([ESI])
2374 if (op.type != MRG || op.base != REG_ESI || op.index != -1 || op.offset != 0 || op.anyoffset != 0) match |= MA_TYP;
2375 if (datasize == 0) datasize = op.size;
2376 if (op.size != 0 && op.size != datasize) match |= MA_DIF;
2377 break;
2378 case MDE: // Destination in string operands ([EDI])
2379 if (op.type != MRG || op.base != REG_EDI || op.index != -1 || op.offset != 0 || op.anyoffset != 0) match |= MA_TYP;
2380 if (op.segment != SEG_UNDEF && op.segment != SEG_ES) match |= MA_SEG;
2381 if (datasize == 0) datasize = op.size;
2382 if (op.size != 0 && op.size != datasize) match |= MA_DIF;
2383 break;
2384 case MXL: // XLAT operand ([EBX+AL])
2385 if (op.type != MXL) match |= MA_TYP;
2386 break;
2387 case IMM: // Immediate data (8 or 16/32)
2388 case IMU: // Immediate unsigned data (8 or 16/32)
2389 if (op.type != IMM) match |= MA_TYP;
2390 break;
2391 case VXD: // VxD service (32-bit only)
2392 if (op.type != IMM) match |= MA_TYP;
2393 if (datasize == 0) datasize = 4;
2394 if (datasize != 4) match |= MA_SIZ;
2395 break;
2396 case JMF: // Immediate absolute far jump/call addr
2397 if (op.type != JMF) match |= MA_TYP;
2398 if ((jmpmode&0x05) != 0) match |= MA_JMP;
2399 jmpmode &= 0x7F;
2400 break;
2401 case JOB: // Immediate byte offset (for jumps)
2402 if (op.type != IMM || longjump) match |= MA_TYP;
2403 if ((jmpmode&0x0A) != 0) match |= MA_JMP;
2404 jmpmode &= 0x7F;
2405 break;
2406 case JOW: // Immediate full offset (for jumps)
2407 if (op.type != IMM) match |= MA_TYP;
2408 if ((jmpmode&0x09) != 0) match |= MA_JMP;
2409 jmpmode &= 0x7F;
2410 break;
2411 case IMA: // Immediate absolute near data address
2412 if (op.type != MRG || op.base >= 0 || op.index >= 0) match |= MA_TYP;
2413 break;
2414 case IMX: // Immediate sign-extendable byte
2415 if (op.type != IMM) match |= MA_TYP;
2416 if (op.offset < -128 || op.offset > 127) match |= MA_RNG;
2417 break;
2418 case C01: // Implicit constant 1 (for shifts)
2419 if (op.type != IMM || (op.offset != 1 && op.anyoffset == 0)) match |= MA_TYP;
2420 break;
2421 case IMS: // Immediate byte (for shifts)
2422 case IM1: // Immediate byte
2423 if (op.type != IMM) match |= MA_TYP;
2424 if (op.offset < -128 || op.offset > 255) match |= MA_RNG;
2425 break;
2426 case IM2: // Immediate word (ENTER/RET)
2427 if (op.type != IMM) match |= MA_TYP;
2428 if (op.offset < 0 || op.offset > 65535) match |= MA_RNG;
2429 break;
2430 case SGM: // Segment register in ModRM byte
2431 if (op.type != SGM) match |= MA_TYP;
2432 if (datasize == 0) datasize = 2;
2433 if (datasize != 2) match |= MA_DIF;
2434 break;
2435 case SCM: // Segment register in command byte
2436 if (op.type != SGM) match |= MA_TYP;
2437 break;
2438 case CRX: // Control register CRx
2439 case DRX: // Debug register DRx
2440 if (op.type != arg) match |= MA_TYP;
2441 if (datasize == 0) datasize = 4;
2442 if (datasize != 4) match |= MA_DIF;
2443 break;
2444 case PRN: // Near return address (pseudooperand)
2445 case PRF: // Far return address (pseudooperand)
2446 case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
2447 case PAH: // AH (in LAHF/SAHF, pseudooperand)
2448 case PFL: // Lower byte of flags (pseudooperand)
2449 case PS0: // Top of FPU stack (pseudooperand)
2450 case PS1: // ST(1) (pseudooperand)
2451 case PCX: // CX/ECX (pseudooperand)
2452 case PDI: // EDI (pseudooperand in MMX extentions)
2453 break;
2454 default: // Undefined type of operand
2455 xstrcpy(errtext, "Internal Assembler error");
2456 goto error;
2457 } // End of switch (arg)
2458 if ((jmpmode&0x80) != 0) match |= MA_JMP;
2459 if (match != 0) break; // Some of the operands doesn't match
2460 } // End of operand matching loop
2461 if (match == 0) {
2462 // Exact match found
2463 if (attempt > 0) {
2464 // Well, try to find yet another match
2465 --attempt;
2466 nameok = 0;
2467 } else {
2468 break;
2471 } // End of command search loop
2472 // Check whether some error was detected. If several errors were found
2473 // similtaneously, report one (roughly in order of significance).
2474 if (nameok == 0) { xstrcpy(errtext, "Unrecognized command"); scdata.asmcmd = nameend; goto error; } // Mnemonic unavailable
2475 if (match != 0) {
2476 // Command not found
2477 if (minop > 0 && aop[minop-1].type == NNN) xstrcpy(errtext, "Too few operands");
2478 else if (maxop < 3 && aop[maxop].type != NNN) xstrcpy(errtext, "Too many operands");
2479 else if (nameok > 1) xstrcpy(errtext, "Command does not support given operands"); // More that 1 command
2480 else if (match&MA_JMP) xstrcpy(errtext, "Invalid jump size modifier");
2481 else if (match&MA_NOP) xstrcpy(errtext, "Wrong number of operands");
2482 else if (match&MA_TYP) xstrcpy(errtext, "Command does not support given operands");
2483 else if (match&MA_NOS) xstrcpy(errtext, "Please specify operand size");
2484 else if (match&MA_SIZ) xstrcpy(errtext, "Bad operand size");
2485 else if (match&MA_DIF) xstrcpy(errtext, "Different size of operands");
2486 else if (match&MA_SEG) xstrcpy(errtext, "Invalid segment register");
2487 else if (match&MA_RNG) xstrcpy(errtext, "Constant out of expected range");
2488 else xstrcpy(errtext, "Erroneous command");
2489 goto error;
2491 // Exact match found. Now construct the code.
2492 hasrm = 0; // Whether command has ModR/M byte
2493 hassib = 0; // Whether command has SIB byte
2494 dispsize = 0; // Size of displacement (if any)
2495 immsize = 0; // Size of immediate data (if any)
2496 segment = SEG_UNDEF; // Necessary segment prefix
2497 jmpsize = 0; // No relative jumps
2498 memset(tcode.ptr, 0, tcode.sizeof);
2499 *cast(uint*)tcode.ptr = pd.code&pd.mask;
2500 memset(tmask.ptr, 0, tmask.sizeof);
2501 *cast(uint*)tmask.ptr = pd.mask;
2502 i = pd.len-1; // Last byte of command itself
2503 if (rep) ++i; // REPxx prefixes count as extra byte
2504 // In some cases at least one operand must have explicit size declaration (as
2505 // in MOV [EAX], 1). This preliminary check does not include all cases.
2506 if (pd.bits == WW || pd.bits == WS || pd.bits == WP) {
2507 if (datasize == 0) { xstrcpy(errtext, "Please specify operand size"); goto error; }
2508 if (datasize > 1) tcode[i] |= 0x01; // WORD or DWORD size of operands
2509 tmask[i] |= 0x01;
2510 } else if (pd.bits == W3) {
2511 if (datasize == 0) { xstrcpy(errtext, "Please specify operand size"); goto error; }
2512 if (datasize > 1) tcode[i] |= 0x08; // WORD or DWORD size of operands
2513 tmask[i] |= 0x08;
2515 // Present suffix of 3DNow! command as immediate byte operand.
2516 if ((pd.type&C_TYPEMASK) == C_NOW) {
2517 immsize = 1;
2518 immediate = (pd.code>>16)&0xFF;
2520 // Process operands again, this time constructing the code.
2521 anydisp = anyimm = anyjmp = 0;
2522 // Up to 3 operands
2523 for (j = 0; j < 3; ++j) {
2524 op = aop.ptr+j;
2525 if (j == 0) arg = pd.arg1;
2526 else if (j == 1) arg = pd.arg2;
2527 else arg = pd.arg3;
2528 if (arg == NNN) break; // All operands processed
2529 switch (arg) {
2530 case REG: // Integer register in Reg field
2531 case RG4: // Integer 4-byte register in Reg field
2532 case RMX: // MMX register MMx
2533 case R3D: // 3DNow! register MMx
2534 case CRX: // Control register CRx
2535 case DRX: // Debug register DRx
2536 hasrm = 1;
2537 if (op.index < 8) { tcode[i+1] |= cast(ubyte)(op.index<<3); tmask[i+1] |= 0x38; }
2538 break;
2539 case RCM: // Integer register in command byte
2540 case RST: // FPU register (ST(i)) in command byte
2541 if (op.index < 8) { tcode[i] |= cast(ubyte)op.index; tmask[i] |= 0x07; }
2542 break;
2543 case RAC: // Accumulator (AL/AX/EAX, implicit)
2544 case RAX: // AX (2-byte, implicit)
2545 case RDX: // DX (16-bit implicit port address)
2546 case RCL: // Implicit CL register (for shifts)
2547 case RS0: // Top of FPU stack (ST(0))
2548 case MDE: // Destination in string op's ([EDI])
2549 case C01: // Implicit constant 1 (for shifts)
2550 break; // Simply skip implicit operands
2551 case MSO: // Source in string op's ([ESI])
2552 case MXL: // XLAT operand ([EBX+AL])
2553 if (op.segment != SEG_UNDEF && op.segment != SEG_DS) segment = op.segment;
2554 break;
2555 case MRG: // Memory/register in ModRM byte
2556 case MRJ: // Memory/reg in ModRM as JUMP target
2557 case MR1: // 1-byte memory/register in ModRM byte
2558 case MR2: // 2-byte memory/register in ModRM byte
2559 case MR4: // 4-byte memory/register in ModRM byte
2560 case RR4: // 4-byte memory/register (register only)
2561 case MR8: // 8-byte memory/MMX register in ModRM
2562 case RR8: // 8-byte MMX register only in ModRM
2563 case MRD: // 8-byte memory/3DNow! register in ModRM
2564 case RRD: // 8-byte memory/3DNow! (register only)
2565 hasrm = 1;
2566 if (op.type != MRG) {
2567 // Register in ModRM byte
2568 tcode[i+1] |= 0xC0; tmask[i+1] |= 0xC0;
2569 if (op.index < 8) { tcode[i+1] |= cast(ubyte)op.index; tmask[i+1] |= 0x07; }
2570 break;
2572 // Note: NO BREAK, continue with address
2573 goto case;
2574 case MMA: // Memory address in ModRM byte for LEA
2575 case MML: // Memory in ModRM byte (for LES)
2576 case MMS: // Memory in ModRM byte (as SEG:OFFS)
2577 case MM6: // Memory in ModRm (6-byte descriptor)
2578 case MMB: // Two adjacent memory locations (BOUND)
2579 case MD2: // Memory in ModRM byte (16-bit integer)
2580 case MB2: // Memory in ModRM byte (16-bit binary)
2581 case MD4: // Memory in ModRM byte (32-bit integer)
2582 case MD8: // Memory in ModRM byte (64-bit integer)
2583 case MDA: // Memory in ModRM byte (80-bit BCD)
2584 case MF4: // Memory in ModRM byte (32-bit float)
2585 case MF8: // Memory in ModRM byte (64-bit float)
2586 case MFA: // Memory in ModRM byte (80-bit float)
2587 case MFE: // Memory in ModRM byte (FPU environment)
2588 case MFS: // Memory in ModRM byte (FPU state)
2589 case MFX: // Memory in ModRM byte (ext. FPU state)
2590 hasrm = 1;
2591 displacement = op.offset;
2592 anydisp = op.anyoffset;
2593 if (op.base < 0 && op.index < 0) {
2594 dispsize = 4; // Special case of immediate address
2595 if (op.segment != SEG_UNDEF && op.segment != SEG_DS) segment = op.segment;
2596 tcode[i+1] |= 0x05;
2597 tmask[i+1] |= 0xC7;
2598 } else if (op.index < 0 && op.base != REG_ESP) {
2599 tmask[i+1] |= 0xC0; // SIB byte unnecessary
2600 if (op.offset == 0 && op.anyoffset == 0 && op.base != REG_EBP) {
2601 // [EBP] always requires offset
2602 } else if ((constsize&1) != 0 && ((op.offset >= -128 && op.offset < 128) || op.anyoffset != 0)) {
2603 tcode[i+1] |= 0x40; // Disp8
2604 dispsize = 1;
2605 } else {
2606 tcode[i+1] |= 0x80; // Disp32
2607 dispsize = 4;
2609 if (op.base < 8) {
2610 if (op.segment != SEG_UNDEF && op.segment != addr32[op.base]) segment = op.segment;
2611 tcode[i+1] |= cast(ubyte)op.base; // Note that case [ESP] has base<0.
2612 tmask[i+1] |= 0x07;
2613 } else {
2614 segment = op.segment;
2616 } else {
2617 // SIB byte necessary
2618 hassib = 1;
2619 // EBP as base requires offset? optimize
2620 if (op.base == REG_EBP && op.index >= 0 && op.scale == 1 && op.offset == 0 && op.anyoffset == 0) { op.base = op.index; op.index = REG_EBP; }
2621 // ESP cannot be an index, reorder
2622 if (op.index == REG_ESP && op.scale <= 1) { op.index = op.base; op.base = REG_ESP; op.scale = 1; }
2623 // No base means 4-byte offset, optimize
2624 if (op.base < 0 && op.index >= 0 && op.scale == 2 && op.offset >= -128 && op.offset < 128 && op.anyoffset == 0) { op.base = op.index; op.scale = 1; }
2625 if (op.index == REG_ESP) { xstrcpy(errtext, "Invalid indexing mode"); goto error; } // Reordering was unsuccessfull
2626 if (op.base < 0) { tcode[i+1] |= 0x04; dispsize = 4; }
2627 else if (op.offset == 0 && op.anyoffset == 0 && op.base != REG_EBP) tcode[i+1] |= 0x04; // No displacement
2628 else if ((constsize&1) != 0 && ((op.offset >= -128 && op.offset < 128) || op.anyoffset != 0)) { tcode[i+1] |= 0x44; dispsize = 1; } // Disp8
2629 else { tcode[i+1] |= 0x84; dispsize = 4; } // Disp32
2630 tmask[i+1] |= 0xC7; // ModRM completed, proceed with SIB
2631 if (op.scale == 2) tcode[i+2] |= 0x40;
2632 else if (op.scale == 4) tcode[i+2] |= 0x80;
2633 else if (op.scale == 8) tcode[i+2] |= 0xC0;
2634 tmask[i+2] |= 0xC0;
2635 if (op.index < 8) {
2636 if (op.index < 0) op.index = 0x04;
2637 tcode[i+2] |= cast(ubyte)(op.index<<3);
2638 tmask[i+2] |= 0x38;
2640 if (op.base < 8) {
2641 if (op.base < 0) op.base = 0x05;
2642 if (op.segment != SEG_UNDEF && op.segment != addr32[op.base]) segment = op.segment;
2643 tcode[i+2] |= cast(ubyte)op.base;
2644 tmask[i+2] |= 0x07;
2645 } else {
2646 segment = op.segment;
2649 break;
2650 case IMM: // Immediate data (8 or 16/32)
2651 case IMU: // Immediate unsigned data (8 or 16/32)
2652 case VXD: // VxD service (32-bit only)
2653 if (datasize == 0 && pd.arg2 == NNN && (pd.bits == SS || pd.bits == WS)) datasize = 4;
2654 if (datasize == 0) { xstrcpy(errtext, "Please specify operand size"); goto error; }
2655 immediate = op.offset;
2656 anyimm = op.anyoffset;
2657 if (pd.bits == SS || pd.bits == WS) {
2658 if (datasize > 1 && (constsize&2) != 0 && ((immediate >= -128 && immediate < 128) || op.anyoffset != 0)) { immsize = 1; tcode[i] |= 0x02; } else immsize = datasize;
2659 tmask[i] |= 0x02;
2660 } else {
2661 immsize = datasize;
2663 break;
2664 case IMX: // Immediate sign-extendable byte
2665 case IMS: // Immediate byte (for shifts)
2666 case IM1: // Immediate byte
2667 if (immsize == 2) {
2668 // To accomodate ENTER instruction
2669 immediate = (immediate&0xFFFF)|(op.offset<<16);
2670 } else {
2671 immediate = op.offset;
2673 anyimm |= op.anyoffset;
2674 ++immsize;
2675 break;
2676 case IM2: // Immediate word (ENTER/RET)
2677 immediate = op.offset;
2678 anyimm = op.anyoffset;
2679 immsize = 2;
2680 break;
2681 case IMA: // Immediate absolute near data address
2682 if (op.segment != SEG_UNDEF && op.segment != SEG_DS) segment = op.segment;
2683 displacement = op.offset;
2684 anydisp = op.anyoffset;
2685 dispsize = 4;
2686 break;
2687 case JOB: // Immediate byte offset (for jumps)
2688 jmpoffset = op.offset;
2689 anyjmp = op.anyoffset;
2690 jmpsize = 1;
2691 break;
2692 case JOW: // Immediate full offset (for jumps)
2693 jmpoffset = op.offset;
2694 anyjmp = op.anyoffset;
2695 jmpsize = 4;
2696 break;
2697 case JMF: // Immediate absolute far jump/call addr
2698 displacement = op.offset;
2699 anydisp = op.anyoffset;
2700 dispsize = 4;
2701 immediate = op.segment;
2702 anyimm = op.anyoffset;
2703 immsize = 2;
2704 break;
2705 case SGM: // Segment register in ModRM byte
2706 hasrm = 1;
2707 if (op.index < 6) { tcode[i+1] |= cast(ubyte)(op.index<<3); tmask[i+1] |= 0x38; }
2708 break;
2709 case SCM: // Segment register in command byte
2710 if (op.index == SEG_FS || op.index == SEG_GS) {
2711 tcode[0] = 0x0F;
2712 tmask[0] = 0xFF;
2713 i = 1;
2714 tcode[i] = cast(ubyte)((op.index<<3)|0x80);
2715 if (strcmp(name.ptr, "PUSH") == 0) tcode[i] |= 0x01;
2717 if (strcmp(name.ptr, "PUSH") == 0)
2718 tcode[i] = cast(ubyte)((op.index<<3)|0x80);
2719 else
2720 tcode[i] = cast(ubyte)((op.index<<3)|0x81);
2722 tmask[i] = 0xFF;
2723 } else if (op.index < 6) {
2724 if (op.index == SEG_CS && strcmp(name.ptr, "POP") == 0) { xstrcpy(errtext, "Unable to POP CS"); goto error; }
2725 tcode[i] = cast(ubyte)((tcode[i]&0xC7)|(op.index<<3));
2726 } else {
2727 tcode[i] &= 0xC7;
2728 tmask[i] &= 0xC7;
2730 break;
2731 case PRN: // Near return address (pseudooperand)
2732 case PRF: // Far return address (pseudooperand)
2733 case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
2734 case PAH: // AH (in LAHF/SAHF, pseudooperand)
2735 case PFL: // Lower byte of flags (pseudooperand)
2736 case PS0: // Top of FPU stack (pseudooperand)
2737 case PS1: // ST(1) (pseudooperand)
2738 case PCX: // CX/ECX (pseudooperand)
2739 case PDI: // EDI (pseudooperand in MMX extentions)
2740 break; // Simply skip preudooperands
2741 default: // Undefined type of operand
2742 xstrcpy(errtext, "Internal Assembler error");
2743 goto error;
2746 // Gather parts of command together in the complete command.
2747 j = 0;
2748 if (lock != 0) {
2749 // Lock prefix specified
2750 model.code[j] = 0xF0;
2751 model.mask[j] = 0xFF;
2752 ++j;
2754 if (datasize == 2 && pd.bits != FF) {
2755 // Data size prefix necessary
2756 model.code[j] = 0x66;
2757 model.mask[j] = 0xFF;
2758 ++j;
2760 if (addrsize == 2) {
2761 // Address size prefix necessary
2762 model.code[j] = 0x67;
2763 model.mask[j] = 0xFF;
2764 ++j;
2766 if (segment != SEG_UNDEF) {
2767 // Segment prefix necessary
2768 if (segment == SEG_ES) model.code[j] = 0x26;
2769 else if (segment == SEG_CS) model.code[j] = 0x2E;
2770 else if (segment == SEG_SS) model.code[j] = 0x36;
2771 else if (segment == SEG_DS) model.code[j] = 0x3E;
2772 else if (segment == SEG_FS) model.code[j] = 0x64;
2773 else if (segment == SEG_GS) model.code[j] = 0x65;
2774 else { xstrcpy(errtext, "Internal Assembler error"); goto error; }
2775 model.mask[j] = 0xFF;
2776 ++j;
2778 if (dispsize > 0) {
2779 memcpy(tcode.ptr+i+1+hasrm+hassib, &displacement, dispsize);
2780 if (anydisp == 0) memset(tmask.ptr+i+1+hasrm+hassib, 0xFF, dispsize);
2782 if (immsize > 0) {
2783 if (immsize == 1) l = 0xFFFFFF00U;
2784 else if (immsize == 2) l = 0xFFFF0000U;
2785 else l = 0;
2786 if ((immediate&l) != 0 && (immediate&l) != l) { xstrcpy(errtext, "Constant does not fit into operand"); goto error; }
2787 memcpy(tcode.ptr+i+1+hasrm+hassib+dispsize, &immediate, immsize);
2788 if (anyimm == 0) memset(tmask.ptr+i+1+hasrm+hassib+dispsize, 0xFF, immsize);
2790 i = i+1+hasrm+hassib+dispsize+immsize;
2791 jmpoffset = jmpoffset-(i+j+jmpsize);
2792 model.jmpsize = jmpsize;
2793 model.jmpoffset = jmpoffset;
2794 model.jmppos = i+j;
2795 if (jmpsize != 0) {
2796 if (ip != 0) {
2797 jmpoffset = jmpoffset-ip;
2798 if (jmpsize == 1 && anyjmp == 0 && (jmpoffset < -128 || jmpoffset >= 128)) {
2799 if (longjump == 0 && (jmpmode&0x03) == 0) { longjump = 1; goto retrylongjump; }
2800 char[256] tbuf = 0;
2801 snprintf(tbuf.ptr, tbuf.length, "Relative jump out of range, use %s LONG form", name.ptr);
2802 xstrcpyx(errtext, tbuf[]);
2803 goto error;
2805 memcpy(tcode.ptr+i, &jmpoffset, jmpsize);
2807 if (anyjmp == 0) memset(tmask.ptr+i, 0xFF, jmpsize);
2808 i += jmpsize;
2810 memcpy(model.code.ptr+j, tcode.ptr, i);
2811 memcpy(model.mask.ptr+j, tmask.ptr, i);
2812 i += j;
2813 model.length = i;
2814 return i; // Positive value: length of code
2815 error:
2816 model.length = 0;
2817 return cast(int)(scdata.acommand.ptr-scdata.asmcmd); // Negative value: position of error