1 // Free Disassembler and Assembler -- Header file
3 // Copyright (C) 2001 Oleh Yuschuk
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.
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*/;
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
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 // ////////////////////////////////////////////////////////////////////////// //
49 enum PSEUDOOP
= 128; // Base for pseudooperands
50 enum TEXTLEN
= 256; // Maximal length of text string
52 // Special command features.
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?
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)
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.
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))
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.
169 // Indexes of segment/selector registers
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
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
= [
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
);
245 foreach (immutable xidx
, ref uint ni
; asmmnemolist
[*np
-'A']) {
246 if (ni
== uint.max
&& xidx
< asmmnemolist
[*np
-'A'].length
-1) {
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 // ////////////////////////////////////////////////////////////////////////// //
861 enum SA_NAME
= 0x0001; // Don't try to decode labels
865 // Types of input tokens reported by scanner.
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
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
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
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
; }
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
972 private void strupr (char* s
) {
973 import core
.stdc
.ctype
: toupper
;
975 *s
= cast(char)toupper(*s
);
980 private void strcpyx (char* d
, const(char)[] s
) {
981 import core
.stdc
.string
: memcpy
;
982 if (d
is null) return;
986 memcpy(d
, s
.ptr
, s
.length
);
991 private void xstrcpy (char[] d
, const(char)* s
) {
992 if (d
.length
== 0) return;
996 if (pos
>= d
.length
) break;
1000 if (pos
< d
.length
) d
.ptr
[pos
] = 0;
1003 private void xstrcpyx (char[] d
, const(char)[] s
) {
1004 if (d
.length
== 0) return;
1006 foreach (char ch
; s
) {
1007 if (ch
== 0 || pos
>= d
.length
) break;
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;
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;
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;
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
{
1043 this (in ref AsmScanData scdata
) {
1044 if (scdata
.scan
== SCAN_UCONST || scdata
.scan
== SCAN_DCONST
) {
1046 ival
= scdata
.idata
;
1047 } else if (scdata
.scan
== SCAN_FCONST
) {
1049 fval
= scdata
.fdata
;
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
) {
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;
1071 op
.type
= SCAN_FCONST
;
1072 if (op
.isSignedInt
) op
.fval
= op
.ival
; else op
.fval
= cast(uint)op
.ival
;
1074 } else if (isAnyInt
) {
1076 if (isSignedInt
) fval
= ival
; else fval
= cast(uint)ival
;
1080 if (!isSignedInt ||
!op
.isSignedInt
) { type
= SCAN_UCONST
; op
.type
= SCAN_UCONST
; }
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; }
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;
1102 if (isFloat || op2
.ival
< 0 || op2
.ival
> 31) { type
= -1; return false; }
1103 if (op2
.isSignedInt
) {
1106 ival
= (cast(uint)ival
)<<op2
.ival
;
1110 if (isFloat || op2
.ival
< 0 || op2
.ival
> 31) { type
= -1; return false; }
1111 if (op2
.isSignedInt
) {
1114 ival
= (cast(uint)ival
)>>op2
.ival
;
1118 if (isFloat
) { type
= -1; return false; }
1122 if (isFloat
) { type
= -1; return false; }
1126 if (isFloat
) { type
= -1; return false; }
1130 if (isFloat
) fval
+= op2
.fval
; else ival
+= op2
.ival
;
1133 if (isFloat
) fval
-= op2
.fval
; else ival
-= op2
.ival
;
1136 if (isFloat
) fval
*= op2
.fval
;
1137 else if (op2
.isSignedInt
) ival
*= op2
.ival
;
1138 else ival
= cast(uint)ival
*cast(uint)op2
.ival
;
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
;
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
;
1152 default: type
= -1; return false;
1158 MathOp
doExpr (int prio
) {
1161 auto saved
= scdata
.save
;
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
);
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
;
1180 scdata
.restore(saved
);
1181 scdata
.asmerror
= "invalid math";
1182 scdata
.scan
= SCAN_ERR
;
1186 auto op1
= doExpr(prio
-1);
1187 if (!op1
.valid
) return op1
;
1189 auto saved
= scdata
.save
;
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
);
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(); }
1212 scdata
.restore(saved
);
1219 void doExpression () {
1220 auto op
= doExpr(MAX_PRIO
);
1221 if (op
.valid
) op
.put(scdata
);
1224 int i
, j
, base
, maxdigit
;
1226 real floating
, divisor
;
1230 scdata
.sdata
[0] = '\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
++;
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
);
1246 // j == 8 means "any register"
1247 for (j
= 0; j
<= 8; ++j
) {
1248 if (strcmp(s
.ptr
, regname
[0][j
].ptr
) != 0) continue;
1251 scdata
.scan
= SCAN_REG8
;
1254 for (j
= 0; j
<= 8; ++j
) {
1255 if (strcmp(s
.ptr
, regname
[1][j
].ptr
) != 0) continue;
1258 scdata
.scan
= SCAN_REG16
;
1261 for (j
= 0; j
<= 8; ++j
) {
1262 if (strcmp(s
.ptr
, regname
[2][j
].ptr
) != 0) continue;
1265 scdata
.scan
= SCAN_REG32
;
1268 for (j
= 0; j
< 6; ++j
) {
1269 if (strcmp(s
.ptr
, segname
[j
].ptr
) != 0) continue;
1272 scdata
.scan
= SCAN_SEG
;
1273 scdata
.skipBlanks(); // Skip trailing spaces
1276 if (strcmp(s
.ptr
, "ST") == 0) {
1278 pcmd
= scdata
.asmcmd
;
1279 scanasm(scdata
, SA_NAME
, resolver
);
1280 if (scdata
.scan
!= SCAN_SYMB || scdata
.idata
!= '(') {
1282 scdata
.asmcmd
= pcmd
;
1284 scdata
.scan
= SCAN_FPU
;
1287 scanasm(scdata
, SA_NAME
, resolver
);
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
;
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
;
1301 scdata
.scan
= SCAN_FPU
;
1304 for (j
= 0; j
<= 8; ++j
) {
1305 if (strcmp(s
.ptr
, fpuname
[j
].ptr
) != 0) continue;
1306 // FPU register (alternative coding)
1308 scdata
.scan
= SCAN_FPU
;
1311 for (j
= 0; j
<= 8; ++j
) {
1312 if (strcmp(s
.ptr
, mmxname
[j
].ptr
) != 0) continue;
1315 scdata
.scan
= SCAN_MMX
;
1318 for (j
= 0; j
<= 8; ++j
) {
1319 if (strcmp(s
.ptr
, crname
[j
].ptr
) != 0) continue;
1322 scdata
.scan
= SCAN_CR
;
1325 for (j
= 0; j
<= 8; ++j
) {
1326 if (strcmp(s
.ptr
, drname
[j
].ptr
) != 0) continue;
1329 scdata
.scan
= SCAN_DR
;
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
1339 scdata
.scan
= SCAN_OPSIZE
;
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
== '.') {
1349 scdata
.skipBlanks(); // Skip trailing spaces
1350 if (!isdigit(*scdata
.asmcmd
)) {
1351 scdata
.asmerror
= "Integer number expected";
1352 scdata
.scan
= SCAN_ERR
;
1355 while (isdigit(*scdata
.asmcmd
)) scdata
.idata
= scdata
.idata
*10+(*scdata
.asmcmd
++)-'0'; // LOCAL index is decimal number!
1356 scdata
.scan
= SCAN_LOCAL
;
1359 if (strcmp(s
.ptr
, "ARG") == 0 && *scdata
.asmcmd
== '.') {
1361 scdata
.skipBlanks(); // Skip trailing spaces
1362 if (!isdigit(*scdata
.asmcmd
)) {
1363 scdata
.asmerror
= "Integer number expected";
1364 scdata
.scan
= SCAN_ERR
;
1367 while (isdigit(*scdata
.asmcmd
)) scdata
.idata
= scdata
.idata
*10+(*scdata
.asmcmd
++)-'0'; // ARG index is decimal number!
1368 scdata
.scan
= SCAN_ARG
;
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
1394 if (resolver
!is null) {
1396 scdata
.idata
= resolver(symname
);
1397 scdata
.scan
= SCAN_UCONST
;
1398 scdata
.skipBlanks();
1400 } catch (Exception
) {}
1402 scdata
.asmerror
= "Unknown identifier";
1403 scdata
.scan
= SCAN_ERR
;
1405 } else if (isdigit(*scdata
.asmcmd
)) {
1407 bool metHexDigit
= false;
1408 auto saved
= scdata
.save
;
1413 if (scdata
.asmcmd
[0] == '0' && toupper(scdata
.asmcmd
[1]) == 'X') { base
= 16; scdata
.asmcmd
+= 2; } // Force hexadecimal number
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;
1421 } else if (isxdigit(*scdata
.asmcmd
)) {
1423 hex
= hex
*16+toupper(*scdata
.asmcmd
++)-'A'+10;
1429 if (maxdigit
== 0) {
1430 scdata
.asmerror
= "Hexadecimal digits after 0x... expected";
1431 scdata
.scan
= SCAN_ERR
;
1434 if (toupper(*scdata
.asmcmd
) == 'H') {
1435 // Force hexadecimal number
1437 scdata
.asmerror
= "Please don't mix 0xXXXX and XXXXh forms";
1438 scdata
.scan
= SCAN_ERR
;
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
);
1451 scdata
.skipBlanks();
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; }
1459 if (isdigit(*scdata
.asmcmd
) ||
toupper(*scdata
.asmcmd
) == 'E') {
1461 // Floating-point number
1462 while (isdigit(*scdata
.asmcmd
)) {
1464 floating
+= divisor
*(*scdata
.asmcmd
-'0');
1467 if (toupper(*scdata
.asmcmd
) == 'E') {
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; }
1472 while (isdigit(*scdata
.asmcmd
)) { if (decimal
< 65536) decimal
= decimal
*10+(*scdata
.asmcmd
++)-'0'; }
1473 //floating *= pow10l(decimal*base);
1476 while (decimal
-- > 0) dx
/= 10;
1479 while (decimal
-- > 0) dx
*= 10;
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
);
1492 scdata
.skipBlanks();
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
);
1505 scdata
.skipBlanks();
1510 // Default is hexadecimal
1511 if (scdata
.defaultHex || metHexDigit || base
== 16) {
1513 scdata
.scan
= SCAN_UCONST
;
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
);
1525 scdata
.skipBlanks();
1528 } else if (*scdata
.asmcmd
== '$' && !isalnum(scdata
.asmcmd
[1])) {
1529 // dollar, current EIP
1530 auto saved
= scdata
.save
;
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
);
1541 scdata
.skipBlanks();
1544 } else if (*scdata
.asmcmd
== '\'' ||
*scdata
.asmcmd
== '`') {
1545 // Character constant
1546 char ech
= *scdata
.asmcmd
++;
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; }
1555 if (*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;
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
;
1570 if (isalpha(scdata
.asmcmd
[-1])) { scdata
.asmerror
= "Invalid escape"; scdata
.scan
= SCAN_ERR
; return; }
1571 cc
[ccpos
++] = scdata
.asmcmd
[-1];
1575 cc
[ccpos
++] = *scdata
.asmcmd
++;
1578 if (*scdata
.asmcmd
!= ech
) { scdata
.asmerror
= "Unterminated character constant"; scdata
.scan
= SCAN_ERR
; return; }
1580 if (ccpos
!= 1 && ccpos
!= 2 && ccpos
!= 4) { scdata
.asmerror
= "Invalid character constant"; scdata
.scan
= SCAN_ERR
; return; }
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;
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
;
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 '+'
1631 scdata
.asmcmd
= pcmd
;
1635 // Any other character
1638 scdata
.scan
= SCAN_SYMB
;
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
;
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
) {
1659 while (scdata
.scan
== SCAN_JMPSIZE
) {
1660 // Fetch all size modifiers
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
;
1672 if ((j
&0x08) == 0) j |
= 0x04; // Force NEAR if not FAR
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
1680 op
.index
= scdata
.idata
;
1681 if (scdata
.scan
== SCAN_REG8
) op
.size
= 1;
1682 else if (scdata
.scan
== SCAN_REG16
) op
.size
= 2;
1684 } else if (scdata
.scan
== SCAN_FPU
) {
1687 op
.index
= scdata
.idata
;
1688 } else if (scdata
.scan
== SCAN_MMX
) {
1689 // MMX or 3DNow! register
1691 op
.index
= scdata
.idata
;
1692 } else if (scdata
.scan
== SCAN_CR
) {
1695 op
.index
= scdata
.idata
;
1696 } else if (scdata
.scan
== SCAN_DR
) {
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
;
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
;
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
) {
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
;
1735 op
.offset
= scdata
.idata
;
1737 if (scdata
.scan
== SCAN_OFS
) op
.anyoffset
= 1;
1739 // Constant without sign
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
;
1748 } else if (scdata
.scan
== SCAN_SEG || scdata
.scan
== SCAN_OPSIZE ||
(scdata
.scan
== SCAN_SYMB
&& scdata
.idata
== '[')) {
1749 // Segment register or address
1751 if (scdata
.scan
== SCAN_SEG
) {
1753 scanasm(scdata
, 0, resolver
);
1754 if (scdata
.scan
!= SCAN_SYMB || scdata
.idata
!= ':') {
1755 // Segment register as operand
1758 return; // Next token already scanned
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).
1767 if (scdata
.scan
== SCAN_SYMB
&& scdata
.idata
== '[') {
1769 if (bracket
) { scdata
.asmerror
= "Only one opening bracket allowed"; scdata
.scan
= SCAN_ERR
; return; }
1771 } else if (scdata
.scan
== SCAN_OPSIZE
) {
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
) {
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
) {
1784 // None of expected address elements
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;
1800 sign
= '+'; // Default sign for the first operand
1802 // Get SIB and offset
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; }
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
;
1820 } else if (scdata
.scan
== SCAN_REG32
) {
1821 if (sign
== '-') { scdata
.asmerror
= "Unable to subtract register"; scdata
.scan
= SCAN_ERR
; return; }
1823 scanasm(scdata
, 0, resolver
);
1824 if (scdata
.scan
== SCAN_SYMB
&& scdata
.idata
== '*') {
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
);
1837 } else if (scdata
.scan
== SCAN_LOCAL
) {
1839 op
.offset
-= scdata
.idata
*4;
1840 scanasm(scdata
, 0, resolver
);
1841 } else if (scdata
.scan
== SCAN_ARG
) {
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
== '*') {
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
);
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; }
1866 // None of expected address elements
1869 if (scdata
.scan
== SCAN_SYMB
&& scdata
.idata
== ']') break;
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; }
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
;
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; }
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; }
1902 scdata
.asmerror
= "Invalid scale";
1903 scdata
.scan
= SCAN_ERR
;
1911 scdata
.asmerror
= "Unrecognized operand";
1912 scdata
.scan
= SCAN_ERR
;
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
;
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
;
1956 const(char)* nameend
;
1957 ubyte[ASMMAXCMDSIZE
] tcode
;
1958 ubyte[ASMMAXCMDSIZE
] tmask
;
1959 AsmOperand
[3] aop
; // Up to 3 operands allowed
1961 immutable(AsmInstrData
)* pd
;
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");
1971 scdata
.acommand
[] = 0;
1972 scdata
.acommand
[0..cmdstr
.length
] = cmdstr
;
1973 scdata
.asmcmd
= scdata
.acommand
.ptr
;
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
1986 model
.jmpoffset
= 0;
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;
1998 putdata(ip
+model
.length
, vb
);
2000 if (bpos
>= model
.code
.length
) { xstrcpy(errtext
, "too many byte constants"); return false; }
2001 model
.code
[bpos
] = vb
;
2002 model
.mask
[bpos
] = 0xff;
2009 bool dbPutConst (uint v
) {
2010 foreach (immutable _
; 0..csize
) {
2011 if (!dbPutByte(v
&0xff)) return false;
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
; }
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
== '"') {
2031 while (*scdata
.asmcmd
&& *scdata
.asmcmd
!= '"') {
2033 if (*scdata
.asmcmd
!= '\\') {
2034 vb
= cast(ubyte)(*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;
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
++);
2050 if (isalpha(scdata
.asmcmd
[-1])) { xstrcpy(errtext
, "Invalid escape"); goto error
; }
2051 vb
= cast(ubyte)scdata
.asmcmd
[-1];
2055 if (!dbPutByte(vb
)) goto error
;
2057 if (*scdata
.asmcmd
== '"') ++scdata
.asmcmd
;
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;
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
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
; }
2078 } else if (scdata
.scan
== SCAN_LOCK
) {
2079 if (lock != 0) { xstrcpy(errtext
, "Duplicated LOCK prefix"); goto error
; }
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
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.
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
2144 // Try all mnemonics (separated by ':')
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;
2152 } else if (pd
.name
[j
] == name
[i
]) {
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
2165 // Comparison failed
2170 if (i
== 0) continue;
2171 } else if (pd
.name
[0] == '$') {
2172 // Mnemonic depends on address size
2176 // Try all mnemonics (separated by ':')
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;
2184 } else if (pd
.name
[j
] == name
[i
]) {
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
2197 // Comparison failed
2202 if (i
== 0) continue;
2204 // Compare with all synonimes
2206 datasize
= 0; // Default settings
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;
2212 if (j
>= pd
.name
.length || pd
.name
[j
] == '\0') break;
2215 if (k
> j
) continue;
2217 // For error diagnostics it is important to know whether mnemonic exists.
2219 if (pd
.arg1
== NNN || pd
.arg1
>= PSEUDOOP
) {
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;
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.
2238 for (j
= 0; j
< 3; ++j
) {
2240 if (j
== 0) arg
= pd
.arg1
;
2241 else if (j
== 1) arg
= pd
.arg2
;
2243 if (arg
== NNN || arg
>= PSEUDOOP
) {
2244 if (op
.type
!= NNN
) match |
= MA_NOP
; // No more arguments
2247 if (op
.type
== NNN
) { match |
= MA_NOP
; break; } // No corresponding operand
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
;
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
;
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
;
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
;
2277 case RS0
: // Top of FPU stack (ST(0))
2278 if (op
.type
!= RST ||
(op
.index
!= 0 && op
.index
!= 8)) match |
= MA_TYP
;
2280 case RST
: // FPU register (ST(i)) in command byte
2281 if (op
.type
!= RST
) match |
= MA_TYP
;
2283 case RMX
: // MMX register MMx
2284 case R3D
: // 3DNow! register MMx
2285 if (op
.type
!= RMX
) match |
= MA_TYP
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
2384 case MXL
: // XLAT operand ([EBX+AL])
2385 if (op
.type
!= MXL
) match |
= MA_TYP
;
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
;
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
;
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
;
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
;
2406 case JOW
: // Immediate full offset (for jumps)
2407 if (op
.type
!= IMM
) match |
= MA_TYP
;
2408 if ((jmpmode
&0x09) != 0) match |
= MA_JMP
;
2411 case IMA
: // Immediate absolute near data address
2412 if (op
.type
!= MRG || op
.base
>= 0 || op
.index
>= 0) match |
= MA_TYP
;
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
;
2418 case C01
: // Implicit constant 1 (for shifts)
2419 if (op
.type
!= IMM ||
(op
.offset
!= 1 && op
.anyoffset
== 0)) match |
= MA_TYP
;
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
;
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
;
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
;
2435 case SCM
: // Segment register in command byte
2436 if (op
.type
!= SGM
) match |
= MA_TYP
;
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
;
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)
2454 default: // Undefined type of operand
2455 xstrcpy(errtext
, "Internal Assembler 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
2462 // Exact match found
2464 // Well, try to find yet another match
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
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");
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
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
2515 // Present suffix of 3DNow! command as immediate byte operand.
2516 if ((pd
.type
&C_TYPEMASK
) == C_NOW
) {
2518 immediate
= (pd
.code
>>16)&0xFF;
2520 // Process operands again, this time constructing the code.
2521 anydisp
= anyimm
= anyjmp
= 0;
2523 for (j
= 0; j
< 3; ++j
) {
2525 if (j
== 0) arg
= pd
.arg1
;
2526 else if (j
== 1) arg
= pd
.arg2
;
2528 if (arg
== NNN
) break; // All operands processed
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
2537 if (op
.index
< 8) { tcode
[i
+1] |
= cast(ubyte)(op
.index
<<3); tmask
[i
+1] |
= 0x38; }
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; }
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
;
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)
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; }
2572 // Note: NO BREAK, continue with address
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)
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
;
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
2606 tcode
[i
+1] |
= 0x80; // Disp32
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.
2614 segment
= op
.segment
;
2617 // SIB byte necessary
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;
2636 if (op
.index
< 0) op
.index
= 0x04;
2637 tcode
[i
+2] |
= cast(ubyte)(op
.index
<<3);
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
;
2646 segment
= op
.segment
;
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
;
2664 case IMX
: // Immediate sign-extendable byte
2665 case IMS
: // Immediate byte (for shifts)
2666 case IM1
: // Immediate byte
2668 // To accomodate ENTER instruction
2669 immediate
= (immediate
&0xFFFF)|
(op
.offset
<<16);
2671 immediate
= op
.offset
;
2673 anyimm |
= op
.anyoffset
;
2676 case IM2
: // Immediate word (ENTER/RET)
2677 immediate
= op
.offset
;
2678 anyimm
= op
.anyoffset
;
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
;
2687 case JOB
: // Immediate byte offset (for jumps)
2688 jmpoffset
= op
.offset
;
2689 anyjmp
= op
.anyoffset
;
2692 case JOW
: // Immediate full offset (for jumps)
2693 jmpoffset
= op
.offset
;
2694 anyjmp
= op
.anyoffset
;
2697 case JMF
: // Immediate absolute far jump/call addr
2698 displacement
= op
.offset
;
2699 anydisp
= op
.anyoffset
;
2701 immediate
= op
.segment
;
2702 anyimm
= op
.anyoffset
;
2705 case SGM
: // Segment register in ModRM byte
2707 if (op
.index
< 6) { tcode
[i
+1] |
= cast(ubyte)(op
.index
<<3); tmask
[i
+1] |
= 0x38; }
2709 case SCM
: // Segment register in command byte
2710 if (op
.index
== SEG_FS || op
.index
== SEG_GS
) {
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);
2720 tcode[i] = cast(ubyte)((op.index<<3)|0x81);
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));
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");
2746 // Gather parts of command together in the complete command.
2749 // Lock prefix specified
2750 model
.code
[j
] = 0xF0;
2751 model
.mask
[j
] = 0xFF;
2754 if (datasize
== 2 && pd
.bits
!= FF
) {
2755 // Data size prefix necessary
2756 model
.code
[j
] = 0x66;
2757 model
.mask
[j
] = 0xFF;
2760 if (addrsize
== 2) {
2761 // Address size prefix necessary
2762 model
.code
[j
] = 0x67;
2763 model
.mask
[j
] = 0xFF;
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;
2779 memcpy(tcode
.ptr
+i
+1+hasrm
+hassib
, &displacement
, dispsize
);
2780 if (anydisp
== 0) memset(tmask
.ptr
+i
+1+hasrm
+hassib
, 0xFF, dispsize
);
2783 if (immsize
== 1) l
= 0xFFFFFF00U
;
2784 else if (immsize
== 2) l
= 0xFFFF0000U
;
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
;
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
; }
2801 snprintf(tbuf
.ptr
, tbuf
.length
, "Relative jump out of range, use %s LONG form", name
.ptr
);
2802 xstrcpyx(errtext
, tbuf
[]);
2805 memcpy(tcode
.ptr
+i
, &jmpoffset
, jmpsize
);
2807 if (anyjmp
== 0) memset(tmask
.ptr
+i
, 0xFF, jmpsize
);
2810 memcpy(model
.code
.ptr
+j
, tcode
.ptr
, i
);
2811 memcpy(model
.mask
.ptr
+j
, tmask
.ptr
, i
);
2814 return i
; // Positive value: length of code
2817 return cast(int)(scdata
.acommand
.ptr
-scdata
.asmcmd
); // Negative value: position of error