1 {
2     Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
3 
4     Contains the abstract assembler implementation for the i386
5 
6     * Portions of this code was inspired by the NASM sources
7       The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
8       Julian Hall. All rights reserved.
9 
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14 
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19 
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 
24  ****************************************************************************
25 }
26 unit aasmcpu;
27 
28 {$i fpcdefs.inc}
29 
30 interface
31 
32     uses
33       globtype,verbose,
34       cpubase,
35       cgbase,cgutils,
36       aasmbase,aasmtai,aasmsym,
37       ogbase;
38 
39     const
40       { "mov reg,reg" source operand number }
41       O_MOV_SOURCE = 0;
42       { "mov reg,reg" destination operand number }
43       O_MOV_DEST = 1;
44 
45     { Operand types }
46       OT_NONE      = $00000000;
47 
48       { Bits 0..7: sizes }
49       OT_BITS8     = $00000001;
50       OT_BITS16    = $00000002;
51       OT_BITS32    = $00000004;
52       OT_BITS64    = $00000008;  { x86_64 and FPU }
53       OT_BITS128   = $10000000;  { 16 byte SSE }
54       OT_BITS256   = $20000000;  { 32 byte AVX }
55       OT_BITS512   = $40000000;  { 64 byte AVX512 }
56       OT_BITS80    = $00000010;  { FPU only  }
57       OT_FAR       = $00000020;  { this means 16:16 or 16:32, like in CALL/JMP }
58       OT_NEAR      = $00000040;
59       OT_SHORT     = $00000080;
60 
61       { TODO: FAR/NEAR/SHORT are sizes too, they should be included into size mask,
62         but this requires adjusting the opcode table }
63       OT_SIZE_MASK = $3000001F;  { all the size attributes  }
64       OT_NON_SIZE  = longint(not OT_SIZE_MASK);
65 
66       { Bits 8..11: modifiers }
67       OT_SIGNED    = $00000100;  { the operand need to be signed -128-127 }
68       OT_TO        = $00000200;  { reverse effect in FADD, FSUB &c  }
69       OT_COLON     = $00000400;  { operand is followed by a colon  }
70       OT_MODIFIER_MASK = $00000F00;
71 
72       { Bits 12..15: type of operand }
73       OT_REGISTER  = $00001000;
74       OT_IMMEDIATE = $00002000;
75       OT_MEMORY    = $0000C000;  { always includes 'OT_REGMEM' bit as well }
76       OT_REGMEM    = $00008000;  { for r/m, ie EA, operands  }
77       OT_TYPE_MASK = OT_REGISTER or OT_IMMEDIATE or OT_MEMORY or OT_REGMEM;
78 
79       OT_REGNORM   = OT_REGISTER or OT_REGMEM;  { 'normal' reg, qualifies as EA  }
80 
81       { Bits 20..22, 24..26: register classes
82         otf_* consts are not used alone, only to build other constants. }
83       otf_reg_cdt  = $00100000;
84       otf_reg_gpr  = $00200000;
85       otf_reg_sreg = $00400000;
86       otf_reg_fpu  = $01000000;
87       otf_reg_mmx  = $02000000;
88       otf_reg_xmm  = $04000000;
89       otf_reg_ymm  = $08000000;
90 
91       otf_reg_extra_mask = $0F000000;
92       { Bits 16..19: subclasses, meaning depends on classes field }
93       otf_sub0     = $00010000;
94       otf_sub1     = $00020000;
95       otf_sub2     = $00040000;
96       otf_sub3     = $00080000;
97       OT_REG_SMASK = otf_sub0 or otf_sub1 or otf_sub2 or otf_sub3;
98 
99       OT_REG_EXTRA_MASK = $0F000000;
100 
101       OT_REG_TYPMASK = otf_reg_cdt or otf_reg_gpr or otf_reg_sreg or otf_reg_extra_mask;
102       { register class 0: CRx, DRx and TRx }
103 {$ifdef x86_64}
104       OT_REG_CDT   = OT_REGISTER or otf_reg_cdt or OT_BITS64;
105 {$else x86_64}
106       OT_REG_CDT   = OT_REGISTER or otf_reg_cdt or OT_BITS32;
107 {$endif x86_64}
108       OT_REG_CREG  = OT_REG_CDT or otf_sub0;  { CRn  }
109       OT_REG_DREG  = OT_REG_CDT or otf_sub1;  { DRn  }
110       OT_REG_TREG  = OT_REG_CDT or otf_sub2;  { TRn  }
111       OT_REG_CR4   = OT_REG_CDT or otf_sub3;  { CR4 (Pentium only)  }
112 
113       { register class 1: general-purpose registers }
114       OT_REG_GPR   = OT_REGNORM or otf_reg_gpr;
115       OT_RM_GPR    = OT_REGMEM or otf_reg_gpr;
116       OT_REG8      = OT_REG_GPR or OT_BITS8;  { 8-bit GPR }
117       OT_REG16     = OT_REG_GPR or OT_BITS16;
118       OT_REG32     = OT_REG_GPR or OT_BITS32;
119       OT_REG64     = OT_REG_GPR or OT_BITS64;
120 
121       { GPR subclass 0: accumulator: AL, AX, EAX or RAX }
122       OT_REG_ACCUM = OT_REG_GPR or otf_sub0;
123       OT_REG_AL    = OT_REG_ACCUM or OT_BITS8;
124       OT_REG_AX    = OT_REG_ACCUM or OT_BITS16;
125       OT_REG_EAX   = OT_REG_ACCUM or OT_BITS32;
126 {$ifdef x86_64}
127       OT_REG_RAX   = OT_REG_ACCUM or OT_BITS64;
128 {$endif x86_64}
129       { GPR subclass 1: counter: CL, CX, ECX or RCX }
130       OT_REG_COUNT = OT_REG_GPR or otf_sub1;
131       OT_REG_CL    = OT_REG_COUNT or OT_BITS8;
132       OT_REG_CX    = OT_REG_COUNT or OT_BITS16;
133       OT_REG_ECX   = OT_REG_COUNT or OT_BITS32;
134 {$ifdef x86_64}
135       OT_REG_RCX   = OT_REG_COUNT or OT_BITS64;
136 {$endif x86_64}
137       { GPR subclass 2: data register: DL, DX, EDX or RDX }
138       OT_REG_DX    = OT_REG_GPR or otf_sub2 or OT_BITS16;
139       OT_REG_EDX   = OT_REG_GPR or otf_sub2 or OT_BITS32;
140 
141       { register class 2: Segment registers }
142       OT_REG_SREG  = OT_REGISTER or otf_reg_sreg or OT_BITS16;
143       OT_REG_CS    = OT_REG_SREG or otf_sub0;  { CS  }
144       OT_REG_DESS  = OT_REG_SREG or otf_sub1;  { DS, ES, SS (non-CS 86 registers)  }
145       OT_REG_FSGS  = OT_REG_SREG or otf_sub2;  { FS, GS (386 extended registers)  }
146 
147       { register class 3: FPU registers }
148       OT_FPUREG    = OT_REGISTER or otf_reg_fpu;
149       OT_FPU0      = OT_FPUREG or otf_sub0;    { FPU stack register zero  }
150 
151       { register class 4: MMX (both reg and r/m) }
152       OT_MMXREG    = OT_REGNORM or otf_reg_mmx;
153       OT_MMXRM     = OT_REGMEM or otf_reg_mmx;
154 
155       { register class 5: XMM (both reg and r/m) }
156       OT_XMMREG    = OT_REGNORM or otf_reg_xmm;
157       OT_XMMRM     = OT_REGMEM or otf_reg_xmm;
158       OT_XMEM32    = OT_REGNORM or otf_reg_xmm or otf_reg_gpr or OT_BITS32;
159       OT_XMEM64    = OT_REGNORM or otf_reg_xmm or otf_reg_gpr or OT_BITS64;
160 
161       { register class 5: XMM (both reg and r/m) }
162       OT_YMMREG    = OT_REGNORM or otf_reg_ymm;
163       OT_YMMRM     = OT_REGMEM or otf_reg_ymm;
164       OT_YMEM32    = OT_REGNORM or otf_reg_ymm or otf_reg_gpr or OT_BITS32;
165       OT_YMEM64    = OT_REGNORM or otf_reg_ymm or otf_reg_gpr or OT_BITS64;
166 
167       { Vector-Memory operands }
168       OT_VMEM_ANY  = OT_XMEM32 or OT_XMEM64 or OT_YMEM32 or OT_YMEM64;
169 
170       { Memory operands }
171       OT_MEM8      = OT_MEMORY or OT_BITS8;
172       OT_MEM16     = OT_MEMORY or OT_BITS16;
173       OT_MEM32     = OT_MEMORY or OT_BITS32;
174       OT_MEM64     = OT_MEMORY or OT_BITS64;
175       OT_MEM128    = OT_MEMORY or OT_BITS128;
176       OT_MEM256    = OT_MEMORY or OT_BITS256;
177       OT_MEM80     = OT_MEMORY or OT_BITS80;
178 
179       OT_MEM_OFFS  = OT_MEMORY or otf_sub0;  { special type of EA  }
180                                              { simple [address] offset  }
181 
182       { Matches any type of r/m operand }
183       OT_MEMORY_ANY = OT_MEMORY or OT_RM_GPR or OT_XMMRM or OT_MMXRM or OT_YMMRM or OT_REG_EXTRA_MASK;
184 
185       { Immediate operands }
186       OT_IMM8      = OT_IMMEDIATE or OT_BITS8;
187       OT_IMM16     = OT_IMMEDIATE or OT_BITS16;
188       OT_IMM32     = OT_IMMEDIATE or OT_BITS32;
189       OT_IMM64     = OT_IMMEDIATE or OT_BITS64;
190 
191       OT_ONENESS   = otf_sub0;  { special type of immediate operand  }
192       OT_UNITY     = OT_IMMEDIATE or OT_ONENESS;  { for shift/rotate instructions  }
193 
194       { Size of the instruction table converted by nasmconv.pas }
195 {$if defined(x86_64)}
196       instabentries = {$i x8664nop.inc}
197 {$elseif defined(i386)}
198       instabentries = {$i i386nop.inc}
199 {$elseif defined(i8086)}
200       instabentries = {$i i8086nop.inc}
201 {$endif}
202       maxinfolen    = 9;
203 
204     type
205       { What an instruction can change. Needed for optimizer and spilling code.
206 
207         Note: The order of this enumeration is should not be changed! }
208       TInsChange = (Ch_None,
209         {Read from a register}
210         Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
211         {write from a register}
212         Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
213         {read and write from/to a register}
214         Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
215         {modify the contents of a register with the purpose of using
216          this changed content afterwards (add/sub/..., but e.g. not rep
217          or movsd)}
218         Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
219         {read individual flag bits from the flags register}
220         Ch_RCarryFlag,Ch_RParityFlag,Ch_RAuxiliaryFlag,Ch_RZeroFlag,Ch_RSignFlag,Ch_ROverflowFlag,
221         {write individual flag bits to the flags register}
222         Ch_WCarryFlag,Ch_WParityFlag,Ch_WAuxiliaryFlag,Ch_WZeroFlag,Ch_WSignFlag,Ch_WOverflowFlag,
223         {set individual flag bits to 0 in the flags register}
224         Ch_W0CarryFlag,Ch_W0ParityFlag,Ch_W0AuxiliaryFlag,Ch_W0ZeroFlag,Ch_W0SignFlag,Ch_W0OverflowFlag,
225         {set individual flag bits to 1 in the flags register}
226         Ch_W1CarryFlag,Ch_W1ParityFlag,Ch_W1AuxiliaryFlag,Ch_W1ZeroFlag,Ch_W1SignFlag,Ch_W1OverflowFlag,
227         {write an undefined value to individual flag bits in the flags register}
228         Ch_WUCarryFlag,Ch_WUParityFlag,Ch_WUAuxiliaryFlag,Ch_WUZeroFlag,Ch_WUSignFlag,Ch_WUOverflowFlag,
229         {read and write flag bits}
230         Ch_RWCarryFlag,Ch_RWParityFlag,Ch_RWAuxiliaryFlag,Ch_RWZeroFlag,Ch_RWSignFlag,Ch_RWOverflowFlag,
231         {more specialized flag bits (not considered part of NR_DEFAULTFLAGS by the compiler)}
232         Ch_RDirFlag,Ch_W0DirFlag,Ch_W1DirFlag,Ch_W0IntFlag,Ch_W1IntFlag,
233         {instruction reads flag bits, according to its condition (used by Jcc/SETcc/CMOVcc)}
234         Ch_RFLAGScc,
235         {read/write/read+write the entire flags/eflags/rflags register}
236         Ch_RFlags, Ch_WFlags, Ch_RWFlags,
237         Ch_FPU,
238         Ch_Rop1, Ch_Wop1, Ch_RWop1, Ch_Mop1,
239         Ch_Rop2, Ch_Wop2, Ch_RWop2, Ch_Mop2,
240         Ch_Rop3, Ch_WOp3, Ch_RWOp3, Ch_Mop3,
241         Ch_Rop4, Ch_WOp4, Ch_RWOp4, Ch_Mop4,
242         { instruction doesn't read it's input register, in case both parameters
243           are the same register (e.g. xor eax,eax; sub eax,eax; sbb eax,eax (reads flags only), etc.) }
244         Ch_NoReadIfEqualRegs,
245         Ch_RMemEDI,Ch_WMemEDI,
246         Ch_All,
247         { x86_64 registers }
248         Ch_RRAX, Ch_RRCX, Ch_RRDX, Ch_RRBX, Ch_RRSP, Ch_RRBP, Ch_RRSI, Ch_RRDI,
249         Ch_WRAX, Ch_WRCX, Ch_WRDX, Ch_WRBX, Ch_WRSP, Ch_WRBP, Ch_WRSI, Ch_WRDI,
250         Ch_RWRAX, Ch_RWRCX, Ch_RWRDX, Ch_RWRBX, Ch_RWRSP, Ch_RWRBP, Ch_RWRSI, Ch_RWRDI,
251         Ch_MRAX, Ch_MRCX, Ch_MRDX, Ch_MRBX, Ch_MRSP, Ch_MRBP, Ch_MRSI, Ch_MRDI
252       );
253 
254       TInsProp = packed record
255         Ch : set of TInsChange;
256       end;
257 
258       TMemRefSizeInfo = (msiUnkown, msiUnsupported, msiNoSize,
259                          msiMultiple, msiMultiple8, msiMultiple16, msiMultiple32,
260                          msiMultiple64, msiMultiple128, msiMultiple256,
261                          msiMemRegSize, msiMemRegx16y32, msiMemRegx32y64, msiMemRegx64y128, msiMemRegx64y256,
262                          msiMem8, msiMem16, msiMem32, msiMem64, msiMem128, msiMem256,
263                          msiXMem32, msiXMem64, msiYMem32, msiYMem64,
264                          msiVMemMultiple, msiVMemRegSize);
265 
266       TConstSizeInfo  = (csiUnkown, csiMultiple, csiNoSize, csiMem8, csiMem16, csiMem32, csiMem64);
267 
268       TInsTabMemRefSizeInfoRec = record
269         MemRefSize  : TMemRefSizeInfo;
270         ExistsSSEAVX: boolean;
271         ConstSize   : TConstSizeInfo;
272       end;
273 
274     const
275       MemRefMultiples: set of TMemRefSizeInfo = [msiMultiple, msiMultiple8,
276                                                  msiMultiple16, msiMultiple32,
277                                                  msiMultiple64, msiMultiple128,
278                                                  msiMultiple256, msiVMemMultiple];
279 
280       MemRefSizeInfoVMems: Set of TMemRefSizeInfo = [msiXMem32, msiXMem64, msiYMem32, msiYMem64,
281                                                      msiVMemMultiple, msiVMemRegSize];
282 
283       InsProp : array[tasmop] of TInsProp =
284 {$if defined(x86_64)}
285         {$i x8664pro.inc}
286 {$elseif defined(i386)}
287         {$i i386prop.inc}
288 {$elseif defined(i8086)}
289         {$i i8086prop.inc}
290 {$endif}
291 
292     type
293       TOperandOrder = (op_intel,op_att);
294 
295       {Instruction flags }
296       tinsflag = (
297         { please keep these in order and in sync with IF_SMASK }
298         IF_SM,                  { size match first two operands  }
299         IF_SM2,
300         IF_SB,                  { unsized operands can't be non-byte  }
301         IF_SW,                  { unsized operands can't be non-word  }
302         IF_SD,                  { unsized operands can't be nondword  }
303 
304         { unsized argument spec }
305         { please keep these in order and in sync with IF_ARMASK }
306         IF_AR0,                 { SB, SW, SD applies to argument 0  }
307         IF_AR1,                 { SB, SW, SD applies to argument 1  }
308         IF_AR2,                 { SB, SW, SD applies to argument 2  }
309 
310         IF_PRIV,                { it's a privileged instruction  }
311         IF_SMM,                 { it's only valid in SMM  }
312         IF_PROT,                { it's protected mode only  }
313         IF_NOX86_64,            { removed instruction in x86_64  }
314         IF_UNDOC,               { it's an undocumented instruction  }
315         IF_FPU,                 { it's an FPU instruction  }
316         IF_MMX,                 { it's an MMX instruction  }
317         { it's a 3DNow! instruction  }
318         IF_3DNOW,
319         { it's a SSE (KNI, MMX2) instruction  }
320         IF_SSE,
321         { SSE2 instructions  }
322         IF_SSE2,
323         { SSE3 instructions  }
324         IF_SSE3,
325         { SSE64 instructions  }
326         IF_SSE64,
327         { SVM instructions  }
328         IF_SVM,
329         { SSE4 instructions  }
330         IF_SSE4,
331         IF_SSSE3,
332         IF_SSE41,
333         IF_SSE42,
334         IF_AVX,
335         IF_AVX2,
336         IF_BMI1,
337         IF_BMI2,
338         IF_16BITONLY,
339         IF_FMA,
340         IF_FMA4,
341         IF_TSX,
342         IF_RAND,
343         IF_XSAVE,
344         IF_PREFETCHWT1,
345 
346         { mask for processor level }
347         { please keep these in order and in sync with IF_PLEVEL }
348         IF_8086,                { 8086 instruction  }
349         IF_186,                 { 186+ instruction  }
350         IF_286,                 { 286+ instruction  }
351         IF_386,                 { 386+ instruction  }
352         IF_486,                 { 486+ instruction  }
353         IF_PENT,                { Pentium instruction  }
354         IF_P6,                  { P6 instruction  }
355         IF_KATMAI,              { Katmai instructions  }
356         IF_WILLAMETTE,          { Willamette instructions }
357         IF_PRESCOTT,            { Prescott instructions }
358         IF_X86_64,
359         IF_SANDYBRIDGE,         { Sandybridge-specific instruction }
360         IF_NEC,                 { NEC V20/V30 instruction }
361 
362         { the following are not strictly part of the processor level, because
363           they are never used standalone, but always in combination with a
364           separate processor level flag. Therefore, they use bits outside of
365           IF_PLEVEL, otherwise they would mess up the processor level they're
366           used in combination with.
367           The following combinations are currently used:
368           [IF_AMD, IF_P6],
369           [IF_CYRIX, IF_486],
370           [IF_CYRIX, IF_PENT],
371           [IF_CYRIX, IF_P6] }
372         IF_CYRIX,               { Cyrix, Centaur or VIA-specific instruction }
373         IF_AMD,                 { AMD-specific instruction  }
374 
375         { added flags }
376         IF_PRE,                 { it's a prefix instruction }
377         IF_PASS2,               { if the instruction can change in a second pass }
378         IF_IMM4,                { immediate operand is a nibble (must be in range [0..15]) }
379         IF_IMM3                 { immediate operand is a triad (must be in range [0..7]) }
380       );
381       tinsflags=set of tinsflag;
382 
383     const
384       IF_SMASK=[IF_SM,IF_SM2,IF_SB,IF_SW,IF_SD];
385       IF_ARMASK=[IF_AR0,IF_AR1,IF_AR2];  { mask for unsized argument spec  }
386       IF_PLEVEL=[IF_8086..IF_NEC]; { mask for processor level }
387 
388     type
389       tinsentry=packed record
390         opcode  : tasmop;
391         ops     : byte;
392         optypes : array[0..max_operands-1] of longint;
393         code    : array[0..maxinfolen] of char;
394         flags   : tinsflags;
395       end;
396       pinsentry=^tinsentry;
397 
398       { alignment for operator }
399       tai_align = class(tai_align_abstract)
400          reg       : tregister;
401          constructor create(b:byte);override;
402          constructor create_op(b: byte; _op: byte);override;
calculatefillbufnull403          function calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;override;
404       end;
405 
406       taicpu = class(tai_cpu_abstract_sym)
407          opsize    : topsize;
408          constructor op_none(op : tasmop);
409          constructor op_none(op : tasmop;_size : topsize);
410 
411          constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
412          constructor op_const(op : tasmop;_size : topsize;_op1 : aint);
413          constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
414 
415          constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
416          constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
417          constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
418 
419          constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
420          constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
421          constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
422 
423          constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
424 
425          constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
426          constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
427          constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
428          constructor op_ref_reg_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2,_op3 : tregister);
429          constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
430          constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
431          constructor op_const_reg_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2, _op3, _op4 : tregister);
432 
433          { this is for Jmp instructions }
434          constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
435 
436          constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
437          constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
438          constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
439          constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
440 
441          procedure changeopsize(siz:topsize);
442 
GetStringnull443          function  GetString:string;
444 
445          { This is a workaround for the GAS non commutative fpu instruction braindamage.
446            Early versions of the UnixWare assembler had a bug where some fpu instructions
447            were reversed and GAS still keeps this "feature" for compatibility.
448            for details: http://sourceware.org/binutils/docs/as/i386_002dBugs.html#i386_002dBugs
449                         http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=372528
450                         http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Caveats
451 
452            Since FPC is "GAS centric" due to its history it generates instructions with the same operand order so
453            when generating output for other assemblers, the opcodes must be fixed before writing them.
454            This function returns the fixed opcodes. Changing the opcodes permanently is no good idea
455            because in case of smartlinking assembler is generated twice so at the second run wrong
456            assembler is generated.
457            }
FixNonCommutativeOpcodesnull458          function FixNonCommutativeOpcodes: tasmop;
459       private
460          FOperandOrder : TOperandOrder;
461          procedure init(_size : topsize); { this need to be called by all constructor }
462       public
463          { the next will reset all instructions that can change in pass 2 }
464          procedure ResetPass1;override;
465          procedure ResetPass2;override;
CheckIfValidnull466          function  CheckIfValid:boolean;
Pass1null467          function  Pass1(objdata:TObjData):longint;override;
468          procedure Pass2(objdata:TObjData);override;
469          procedure SetOperandOrder(order:TOperandOrder);
is_same_reg_movenull470          function is_same_reg_move(regtype: Tregistertype):boolean;override;
471          { register spilling code }
spilling_get_operation_typenull472          function spilling_get_operation_type(opnr: longint): topertype;override;
473 {$ifdef i8086}
474          procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
475 {$endif i8086}
476          property OperandOrder : TOperandOrder read FOperandOrder;
477       private
478          { next fields are filled in pass1, so pass2 is faster }
479          insentry  : PInsEntry;
480          insoffset : longint;
481          LastInsOffset : longint; { need to be public to be reset }
482          inssize   : shortint;
483 {$ifdef x86_64}
484          rex       : byte;
485 {$endif x86_64}
InsEndnull486          function  InsEnd:longint;
487          procedure create_ot(objdata:TObjData);
Matchesnull488          function  Matches(p:PInsEntry):boolean;
calcsizenull489          function  calcsize(p:PInsEntry):shortint;
490          procedure gencode(objdata:TObjData);
NeedAddrPrefixnull491          function  NeedAddrPrefix(opidx:byte):boolean;
NeedAddrPrefixnull492          function  NeedAddrPrefix:boolean;
493          procedure write0x66prefix(objdata:TObjData);
494          procedure write0x67prefix(objdata:TObjData);
495          procedure Swapoperands;
FindInsentrynull496          function  FindInsentry(objdata:TObjData):boolean;
497       end;
498 
is_64_bit_refnull499     function is_64_bit_ref(const ref:treference):boolean;
is_32_bit_refnull500     function is_32_bit_ref(const ref:treference):boolean;
is_16_bit_refnull501     function is_16_bit_ref(const ref:treference):boolean;
get_ref_address_sizenull502     function get_ref_address_size(const ref:treference):byte;
get_default_segment_of_refnull503     function get_default_segment_of_ref(const ref:treference):tregister;
504     procedure optimize_ref(var ref:treference; inlineasm: boolean);
505 
spilling_create_loadnull506     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
spilling_create_storenull507     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
508 
MemRefInfonull509     function MemRefInfo(aAsmop: TAsmOp): TInsTabMemRefSizeInfoRec;
510 
511     procedure InitAsm;
512     procedure DoneAsm;
513 
514 
515 {*****************************************************************************
516                               External Symbol Chain
517                               used for agx86nsm and agx86int
518 *****************************************************************************}
519 
520     type
521       PExternChain = ^TExternChain;
522 
523       TExternChain = Record
524         psym : pshortstring;
525         is_defined : boolean;
526         next : PExternChain;
527       end;
528 
529     const
530       FEC : PExternChain = nil;
531 
532     procedure AddSymbol(symname : string; defined : boolean);
533     procedure FreeExternChainList;
534 
535 implementation
536 
537      uses
538        cutils,
539        globals,
540        systems,
541        itcpugas,
542        cpuinfo;
543 
544 
545 
546     procedure AddSymbol(symname : string; defined : boolean);
547     var
548        EC : PExternChain;
549     begin
550       EC:=FEC;
551       while assigned(EC) do
552         begin
553           if EC^.psym^=symname then
554             begin
555               if defined then
556                 EC^.is_defined:=true;
557               exit;
558             end;
559           EC:=EC^.next;
560         end;
561       New(EC);
562       EC^.next:=FEC;
563       FEC:=EC;
564       FEC^.psym:=stringdup(symname);
565       FEC^.is_defined := defined;
566     end;
567 
568     procedure FreeExternChainList;
569     var
570        EC : PExternChain;
571     begin
572       EC:=FEC;
573       while assigned(EC) do
574         begin
575           FEC:=EC^.next;
576           stringdispose(EC^.psym);
577           Dispose(EC);
578           EC:=FEC;
579         end;
580     end;
581 
582 {*****************************************************************************
583                               Instruction table
584 *****************************************************************************}
585 
586      type
587        TInsTabCache=array[TasmOp] of longint;
588        PInsTabCache=^TInsTabCache;
589 
590        TInsTabMemRefSizeInfoCache=array[TasmOp] of TInsTabMemRefSizeInfoRec;
591        PInsTabMemRefSizeInfoCache=^TInsTabMemRefSizeInfoCache;
592 
593      const
594 {$if defined(x86_64)}
595        InsTab:array[0..instabentries-1] of TInsEntry={$i x8664tab.inc}
596 {$elseif defined(i386)}
597        InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
598 {$elseif defined(i8086)}
599        InsTab:array[0..instabentries-1] of TInsEntry={$i i8086tab.inc}
600 {$endif}
601      var
602        InsTabCache : PInsTabCache;
603        InsTabMemRefSizeInfoCache: PInsTabMemRefSizeInfoCache;
604      const
605 {$if defined(x86_64)}
606        { Intel style operands ! }
607        opsize_2_type:array[0..2,topsize] of longint=(
608          (OT_NONE,
609           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
610           OT_BITS16,OT_BITS32,OT_BITS64,
611           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
612           OT_BITS64,
613           OT_NEAR,OT_FAR,OT_SHORT,
614           OT_NONE,
615           OT_BITS128,
616           OT_BITS256,
617           OT_BITS512
618          ),
619          (OT_NONE,
620           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
621           OT_BITS16,OT_BITS32,OT_BITS64,
622           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
623           OT_BITS64,
624           OT_NEAR,OT_FAR,OT_SHORT,
625           OT_NONE,
626           OT_BITS128,
627           OT_BITS256,
628           OT_BITS512
629          ),
630          (OT_NONE,
631           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
632           OT_BITS16,OT_BITS32,OT_BITS64,
633           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
634           OT_BITS64,
635           OT_NEAR,OT_FAR,OT_SHORT,
636           OT_NONE,
637           OT_BITS128,
638           OT_BITS256,
639           OT_BITS512
640          )
641        );
642 
643       reg_ot_table : array[tregisterindex] of longint = (
644         {$i r8664ot.inc}
645       );
646 {$elseif defined(i386)}
647        { Intel style operands ! }
648        opsize_2_type:array[0..2,topsize] of longint=(
649          (OT_NONE,
650           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
651           OT_BITS16,OT_BITS32,OT_BITS64,
652           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
653           OT_BITS64,
654           OT_NEAR,OT_FAR,OT_SHORT,
655           OT_NONE,
656           OT_BITS128,
657           OT_BITS256,
658           OT_BITS512
659          ),
660          (OT_NONE,
661           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
662           OT_BITS16,OT_BITS32,OT_BITS64,
663           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
664           OT_BITS64,
665           OT_NEAR,OT_FAR,OT_SHORT,
666           OT_NONE,
667           OT_BITS128,
668           OT_BITS256,
669           OT_BITS512
670          ),
671          (OT_NONE,
672           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
673           OT_BITS16,OT_BITS32,OT_BITS64,
674           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
675           OT_BITS64,
676           OT_NEAR,OT_FAR,OT_SHORT,
677           OT_NONE,
678           OT_BITS128,
679           OT_BITS256,
680           OT_BITS512
681          )
682       );
683 
684       reg_ot_table : array[tregisterindex] of longint = (
685         {$i r386ot.inc}
686       );
687 {$elseif defined(i8086)}
688        { Intel style operands ! }
689        opsize_2_type:array[0..2,topsize] of longint=(
690          (OT_NONE,
691           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
692           OT_BITS16,OT_BITS32,OT_BITS64,
693           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
694           OT_BITS64,
695           OT_NEAR,OT_FAR,OT_SHORT,
696           OT_NONE,
697           OT_BITS128,
698           OT_BITS256,
699           OT_BITS512
700          ),
701          (OT_NONE,
702           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
703           OT_BITS16,OT_BITS32,OT_BITS64,
704           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
705           OT_BITS64,
706           OT_NEAR,OT_FAR,OT_SHORT,
707           OT_NONE,
708           OT_BITS128,
709           OT_BITS256,
710           OT_BITS512
711          ),
712          (OT_NONE,
713           OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
714           OT_BITS16,OT_BITS32,OT_BITS64,
715           OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
716           OT_BITS64,
717           OT_NEAR,OT_FAR,OT_SHORT,
718           OT_NONE,
719           OT_BITS128,
720           OT_BITS256,
721           OT_BITS512
722          )
723       );
724 
725       reg_ot_table : array[tregisterindex] of longint = (
726         {$i r8086ot.inc}
727       );
728 {$endif}
729 
MemRefInfonull730     function MemRefInfo(aAsmop: TAsmOp): TInsTabMemRefSizeInfoRec;
731     begin
732       result := InsTabMemRefSizeInfoCache^[aAsmop];
733     end;
734 
735     { Operation type for spilling code }
736     type
737       toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
738     var
739       operation_type_table : ^toperation_type_table;
740 
741 
742 {****************************************************************************
743                               TAI_ALIGN
744  ****************************************************************************}
745 
746     constructor tai_align.create(b: byte);
747       begin
748         inherited create(b);
749         reg:=NR_ECX;
750       end;
751 
752 
753     constructor tai_align.create_op(b: byte; _op: byte);
754       begin
755         inherited create_op(b,_op);
756         reg:=NR_NO;
757       end;
758 
759 
tai_align.calculatefillbufnull760     function tai_align.calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;
761       const
762         { Updated according to
763           Software Optimization Guide for AMD Family 15h Processors, Verison 3.08, January 2014
764           and
765           Intel 64 and IA-32 Architectures Software Developer’s Manual
766             Volume 2B: Instruction Set Reference, N-Z, January 2015
767         }
768         alignarray_cmovcpus:array[0..10] of string[11]=(
769           #$66#$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
770           #$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
771           #$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
772           #$0F#$1F#$84#$00#$00#$00#$00#$00,
773           #$0F#$1F#$80#$00#$00#$00#$00,
774           #$66#$0F#$1F#$44#$00#$00,
775           #$0F#$1F#$44#$00#$00,
776           #$0F#$1F#$40#$00,
777           #$0F#$1F#$00,
778           #$66#$90,
779           #$90);
780 {$ifdef i8086}
781         alignarray:array[0..5] of string[8]=(
782           #$90#$90#$90#$90#$90#$90#$90,
783           #$90#$90#$90#$90#$90#$90,
784           #$90#$90#$90#$90,
785           #$90#$90#$90,
786           #$90#$90,
787           #$90);
788 {$else i8086}
789         alignarray:array[0..5] of string[8]=(
790           #$8D#$B4#$26#$00#$00#$00#$00,
791           #$8D#$B6#$00#$00#$00#$00,
792           #$8D#$74#$26#$00,
793           #$8D#$76#$00,
794           #$89#$F6,
795           #$90);
796 {$endif i8086}
797       var
798         bufptr : pchar;
799         j : longint;
800         localsize: byte;
801       begin
802         inherited calculatefillbuf(buf,executable);
803         if not(use_op) and executable then
804          begin
805            bufptr:=pchar(@buf);
806            { fillsize may still be used afterwards, so don't modify }
807            { e.g. writebytes(hp.calculatefillbuf(buf)^,hp.fillsize) }
808            localsize:=fillsize;
809            while (localsize>0) do
810             begin
811 {$ifndef i8086}
812               if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
813                 begin
814                   for j:=low(alignarray_cmovcpus) to high(alignarray_cmovcpus) do
815                    if (localsize>=length(alignarray_cmovcpus[j])) then
816                     break;
817                   move(alignarray_cmovcpus[j][1],bufptr^,length(alignarray_cmovcpus[j]));
818                   inc(bufptr,length(alignarray_cmovcpus[j]));
819                   dec(localsize,length(alignarray_cmovcpus[j]));
820                 end
821               else
822 {$endif not i8086}
823                 begin
824                   for j:=low(alignarray) to high(alignarray) do
825                    if (localsize>=length(alignarray[j])) then
826                     break;
827                   move(alignarray[j][1],bufptr^,length(alignarray[j]));
828                   inc(bufptr,length(alignarray[j]));
829                   dec(localsize,length(alignarray[j]));
830                 end
831             end;
832          end;
833         calculatefillbuf:=pchar(@buf);
834       end;
835 
836 
837 {*****************************************************************************
838                                  Taicpu Constructors
839 *****************************************************************************}
840 
841     procedure taicpu.changeopsize(siz:topsize);
842       begin
843         opsize:=siz;
844       end;
845 
846 
847     procedure taicpu.init(_size : topsize);
848       begin
849          { default order is att }
850          FOperandOrder:=op_att;
851          segprefix:=NR_NO;
852          opsize:=_size;
853          insentry:=nil;
854          LastInsOffset:=-1;
855          InsOffset:=0;
856          InsSize:=0;
857       end;
858 
859 
860     constructor taicpu.op_none(op : tasmop);
861       begin
862          inherited create(op);
863          init(S_NO);
864       end;
865 
866 
867     constructor taicpu.op_none(op : tasmop;_size : topsize);
868       begin
869          inherited create(op);
870          init(_size);
871       end;
872 
873 
874     constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
875       begin
876          inherited create(op);
877          init(_size);
878          ops:=1;
879          loadreg(0,_op1);
880       end;
881 
882 
883     constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aint);
884       begin
885          inherited create(op);
886          init(_size);
887          ops:=1;
888          loadconst(0,_op1);
889       end;
890 
891 
892     constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
893       begin
894          inherited create(op);
895          init(_size);
896          ops:=1;
897          loadref(0,_op1);
898       end;
899 
900 
901     constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
902       begin
903          inherited create(op);
904          init(_size);
905          ops:=2;
906          loadreg(0,_op1);
907          loadreg(1,_op2);
908       end;
909 
910 
911     constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
912       begin
913          inherited create(op);
914          init(_size);
915          ops:=2;
916          loadreg(0,_op1);
917          loadconst(1,_op2);
918       end;
919 
920 
921     constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
922       begin
923          inherited create(op);
924          init(_size);
925          ops:=2;
926          loadreg(0,_op1);
927          loadref(1,_op2);
928       end;
929 
930 
931     constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
932       begin
933          inherited create(op);
934          init(_size);
935          ops:=2;
936          loadconst(0,_op1);
937          loadreg(1,_op2);
938       end;
939 
940 
941     constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
942       begin
943          inherited create(op);
944          init(_size);
945          ops:=2;
946          loadconst(0,_op1);
947          loadconst(1,_op2);
948       end;
949 
950 
951     constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
952       begin
953          inherited create(op);
954          init(_size);
955          ops:=2;
956          loadconst(0,_op1);
957          loadref(1,_op2);
958       end;
959 
960 
961     constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
962       begin
963          inherited create(op);
964          init(_size);
965          ops:=2;
966          loadref(0,_op1);
967          loadreg(1,_op2);
968       end;
969 
970 
971     constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
972       begin
973          inherited create(op);
974          init(_size);
975          ops:=3;
976          loadreg(0,_op1);
977          loadreg(1,_op2);
978          loadreg(2,_op3);
979       end;
980 
981 
982     constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
983       begin
984          inherited create(op);
985          init(_size);
986          ops:=3;
987          loadconst(0,_op1);
988          loadreg(1,_op2);
989          loadreg(2,_op3);
990       end;
991 
992 
993     constructor taicpu.op_ref_reg_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2,_op3 : tregister);
994       begin
995          inherited create(op);
996          init(_size);
997          ops:=3;
998          loadref(0,_op1);
999          loadreg(1,_op2);
1000          loadreg(2,_op3);
1001       end;
1002 
1003 
1004     constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
1005       begin
1006          inherited create(op);
1007          init(_size);
1008          ops:=3;
1009          loadconst(0,_op1);
1010          loadref(1,_op2);
1011          loadreg(2,_op3);
1012       end;
1013 
1014 
1015     constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
1016       begin
1017          inherited create(op);
1018          init(_size);
1019          ops:=3;
1020          loadconst(0,_op1);
1021          loadreg(1,_op2);
1022          loadref(2,_op3);
1023       end;
1024 
1025 
1026     constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
1027       begin
1028         inherited create(op);
1029         init(_size);
1030         ops:=3;
1031         loadreg(0,_op1);
1032         loadreg(1,_op2);
1033         loadref(2,_op3);
1034       end;
1035 
1036     constructor taicpu.op_const_reg_reg_reg(op : tasmop; _size : topsize; _op1 : aint; _op2, _op3, _op4 : tregister);
1037       begin
1038         inherited create(op);
1039         init(_size);
1040         ops:=4;
1041         loadconst(0,_op1);
1042         loadreg(1,_op2);
1043         loadreg(2,_op3);
1044         loadreg(3,_op4);
1045       end;
1046 
1047 
1048     constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
1049       begin
1050          inherited create(op);
1051          init(_size);
1052          condition:=cond;
1053          ops:=1;
1054          loadsymbol(0,_op1,0);
1055       end;
1056 
1057 
1058     constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
1059       begin
1060          inherited create(op);
1061          init(_size);
1062          ops:=1;
1063          loadsymbol(0,_op1,0);
1064       end;
1065 
1066 
1067     constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
1068       begin
1069          inherited create(op);
1070          init(_size);
1071          ops:=1;
1072          loadsymbol(0,_op1,_op1ofs);
1073       end;
1074 
1075 
1076     constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
1077       begin
1078          inherited create(op);
1079          init(_size);
1080          ops:=2;
1081          loadsymbol(0,_op1,_op1ofs);
1082          loadreg(1,_op2);
1083       end;
1084 
1085 
1086     constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
1087       begin
1088          inherited create(op);
1089          init(_size);
1090          ops:=2;
1091          loadsymbol(0,_op1,_op1ofs);
1092          loadref(1,_op2);
1093       end;
1094 
1095 
taicpu.GetStringnull1096     function taicpu.GetString:string;
1097       var
1098         i : longint;
1099         s : string;
1100         addsize : boolean;
1101       begin
1102         s:='['+std_op2str[opcode];
1103         for i:=0 to ops-1 do
1104          begin
1105            with oper[i]^ do
1106              begin
1107                if i=0 then
1108                 s:=s+' '
1109                else
1110                 s:=s+',';
1111                { type }
1112                addsize:=false;
1113                if (ot and OT_REG_EXTRA_MASK)=OT_XMMREG then
1114                 s:=s+'xmmreg'
1115                else
1116                  if (ot and OT_REG_EXTRA_MASK)=OT_YMMREG then
1117                   s:=s+'ymmreg'
1118                else
1119                  if (ot and OT_REG_EXTRA_MASK)=OT_MMXREG then
1120                   s:=s+'mmxreg'
1121                else
1122                  if (ot and OT_REG_EXTRA_MASK)=OT_FPUREG then
1123                   s:=s+'fpureg'
1124                else
1125                 if (ot and OT_REGISTER)=OT_REGISTER then
1126                  begin
1127                    s:=s+'reg';
1128                    addsize:=true;
1129                  end
1130                else
1131                 if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
1132                  begin
1133                    s:=s+'imm';
1134                    addsize:=true;
1135                  end
1136                else
1137                 if (ot and OT_MEMORY)=OT_MEMORY then
1138                  begin
1139                    s:=s+'mem';
1140                    addsize:=true;
1141                  end
1142                else
1143                  s:=s+'???';
1144                { size }
1145                if addsize then
1146                 begin
1147                   if (ot and OT_BITS8)<>0 then
1148                     s:=s+'8'
1149                   else
1150                    if (ot and OT_BITS16)<>0 then
1151                     s:=s+'16'
1152                   else
1153                    if (ot and OT_BITS32)<>0 then
1154                     s:=s+'32'
1155                   else
1156                    if (ot and OT_BITS64)<>0 then
1157                     s:=s+'64'
1158                   else
1159                    if (ot and OT_BITS128)<>0 then
1160                     s:=s+'128'
1161                   else
1162                    if (ot and OT_BITS256)<>0 then
1163                     s:=s+'256'
1164                   else
1165                     s:=s+'??';
1166                   { signed }
1167                   if (ot and OT_SIGNED)<>0 then
1168                    s:=s+'s';
1169                 end;
1170              end;
1171          end;
1172         GetString:=s+']';
1173       end;
1174 
1175 
1176     procedure taicpu.Swapoperands;
1177       var
1178         p : POper;
1179       begin
1180         { Fix the operands which are in AT&T style and we need them in Intel style }
1181         case ops of
1182           0,1:
1183             ;
1184           2 : begin
1185                 { 0,1 -> 1,0 }
1186                 p:=oper[0];
1187                 oper[0]:=oper[1];
1188                 oper[1]:=p;
1189               end;
1190           3 : begin
1191                 { 0,1,2 -> 2,1,0 }
1192                 p:=oper[0];
1193                 oper[0]:=oper[2];
1194                 oper[2]:=p;
1195               end;
1196           4 : begin
1197                 { 0,1,2,3 -> 3,2,1,0 }
1198                 p:=oper[0];
1199                 oper[0]:=oper[3];
1200                 oper[3]:=p;
1201                 p:=oper[1];
1202                 oper[1]:=oper[2];
1203                 oper[2]:=p;
1204               end;
1205           else
1206             internalerror(201108141);
1207         end;
1208       end;
1209 
1210 
1211     procedure taicpu.SetOperandOrder(order:TOperandOrder);
1212       begin
1213         if FOperandOrder<>order then
1214          begin
1215            Swapoperands;
1216            FOperandOrder:=order;
1217          end;
1218       end;
1219 
1220 
taicpu.FixNonCommutativeOpcodesnull1221     function taicpu.FixNonCommutativeOpcodes: tasmop;
1222       begin
1223         result:=opcode;
1224 
1225         { we need ATT order }
1226         SetOperandOrder(op_att);
1227 
1228         if (
1229             (ops=2) and
1230             (oper[0]^.typ=top_reg) and
1231             (oper[1]^.typ=top_reg) and
1232            { if the first is ST and the second is also a register
1233              it is necessarily ST1 .. ST7 }
1234             ((oper[0]^.reg=NR_ST) or
1235              (oper[0]^.reg=NR_ST0))
1236            ) or
1237            { ((ops=1) and
1238             (oper[0]^.typ=top_reg) and
1239             (oper[0]^.reg in [R_ST1..R_ST7]))  or}
1240            (ops=0) then
1241           begin
1242             if opcode=A_FSUBR then
1243               result:=A_FSUB
1244             else if opcode=A_FSUB then
1245               result:=A_FSUBR
1246             else if opcode=A_FDIVR then
1247               result:=A_FDIV
1248             else if opcode=A_FDIV then
1249               result:=A_FDIVR
1250             else if opcode=A_FSUBRP then
1251               result:=A_FSUBP
1252             else if opcode=A_FSUBP then
1253               result:=A_FSUBRP
1254             else if opcode=A_FDIVRP then
1255               result:=A_FDIVP
1256             else if opcode=A_FDIVP then
1257               result:=A_FDIVRP;
1258           end;
1259         if (
1260             (ops=1) and
1261             (oper[0]^.typ=top_reg) and
1262             (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
1263             (oper[0]^.reg<>NR_ST)
1264            ) then
1265          begin
1266            if opcode=A_FSUBRP then
1267              result:=A_FSUBP
1268            else if opcode=A_FSUBP then
1269              result:=A_FSUBRP
1270            else if opcode=A_FDIVRP then
1271              result:=A_FDIVP
1272            else if opcode=A_FDIVP then
1273              result:=A_FDIVRP;
1274          end;
1275       end;
1276 
1277 
1278 {*****************************************************************************
1279                                 Assembler
1280 *****************************************************************************}
1281 
1282     type
1283       ea = packed record
1284         sib_present : boolean;
1285         bytes : byte;
1286         size  : byte;
1287         modrm : byte;
1288         sib   : byte;
1289 {$ifdef x86_64}
1290         rex   : byte;
1291 {$endif x86_64}
1292       end;
1293 
1294     procedure taicpu.create_ot(objdata:TObjData);
1295       {
1296         this function will also fix some other fields which only needs to be once
1297       }
1298       var
1299         i,l,relsize : longint;
1300         currsym : TObjSymbol;
1301       begin
1302         if ops=0 then
1303          exit;
1304         { update oper[].ot field }
1305         for i:=0 to ops-1 do
1306          with oper[i]^ do
1307           begin
1308             case typ of
1309               top_reg :
1310                 begin
1311                   ot:=reg_ot_table[findreg_by_number(reg)];
1312                 end;
1313               top_ref :
1314                 begin
1315                   if (ref^.refaddr=addr_no)
1316 {$ifdef i386}
1317                      or (
1318                          (ref^.refaddr in [addr_pic]) and
1319                          (ref^.base<>NR_NO)
1320                         )
1321 {$endif i386}
1322 {$ifdef x86_64}
1323                      or (
1324                          (ref^.refaddr in [addr_pic,addr_pic_no_got]) and
1325                          (ref^.base<>NR_NO)
1326                         )
1327 {$endif x86_64}
1328                      then
1329                     begin
1330                       { create ot field }
1331                       if (reg_ot_table[findreg_by_number(ref^.base)] and OT_REG_GPR = OT_REG_GPR) and
1332                          ((reg_ot_table[findreg_by_number(ref^.index)] = OT_XMMREG) or
1333                           (reg_ot_table[findreg_by_number(ref^.index)] = OT_YMMREG)
1334                          ) then
1335                         // AVX2 - vector-memory-referenz (e.g. vgatherdpd xmm0, [rax  xmm1], xmm2)
1336                         ot := (reg_ot_table[findreg_by_number(ref^.base)] and OT_REG_GPR) or
1337                               (reg_ot_table[findreg_by_number(ref^.index)])
1338                       else if (ref^.base = NR_NO) and
1339                               ((reg_ot_table[findreg_by_number(ref^.index)] = OT_XMMREG) or
1340                                (reg_ot_table[findreg_by_number(ref^.index)] = OT_YMMREG)
1341                               ) then
1342                         // AVX2 - vector-memory-referenz without base-register (e.g. vgatherdpd xmm0, [xmm1], xmm2)
1343                         ot := (OT_REG_GPR) or
1344                               (reg_ot_table[findreg_by_number(ref^.index)])
1345 
1346                       else if (ot and OT_SIZE_MASK)=0 then
1347                         ot:=OT_MEMORY_ANY or opsize_2_type[i,opsize]
1348                       else
1349                         ot:=OT_MEMORY_ANY or (ot and OT_SIZE_MASK);
1350                       if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
1351                         ot:=ot or OT_MEM_OFFS;
1352                       { fix scalefactor }
1353                       if (ref^.index=NR_NO) then
1354                        ref^.scalefactor:=0
1355                       else
1356                        if (ref^.scalefactor=0) then
1357                         ref^.scalefactor:=1;
1358                     end
1359                   else
1360                     begin
1361                       { Jumps use a relative offset which can be 8bit,
1362                         for other opcodes we always need to generate the full
1363                         32bit address }
1364                       if assigned(objdata) and
1365                          is_jmp then
1366                         begin
1367                           currsym:=objdata.symbolref(ref^.symbol);
1368                           l:=ref^.offset;
1369 {$push}
1370 {$r-,q-} { disable also overflow as address returns a qword for x86_64 }
1371                           if assigned(currsym) then
1372                             inc(l,currsym.address);
1373 {$pop}
1374                           { when it is a forward jump we need to compensate the
1375                             offset of the instruction since the previous time,
1376                             because the symbol address is then still using the
1377                             'old-style' addressing.
1378                             For backwards jumps this is not required because the
1379                             address of the symbol is already adjusted to the
1380                             new offset }
1381                           if (l>InsOffset) and (LastInsOffset<>-1) then
1382                             inc(l,InsOffset-LastInsOffset);
1383                           { instruction size will then always become 2 (PFV) }
1384                           relsize:=(InsOffset+2)-l;
1385                           if (relsize>=-128) and (relsize<=127) and
1386                              (
1387                               not assigned(currsym) or
1388                               (currsym.objsection=objdata.currobjsec)
1389                              ) then
1390                             ot:=OT_IMM8 or OT_SHORT
1391                           else
1392 {$ifdef i8086}
1393                             ot:=OT_IMM16 or OT_NEAR;
1394 {$else i8086}
1395                             ot:=OT_IMM32 or OT_NEAR;
1396 {$endif i8086}
1397                         end
1398                       else
1399 {$ifdef i8086}
1400                         if opsize=S_FAR then
1401                           ot:=OT_IMM16 or OT_FAR
1402                         else
1403                           ot:=OT_IMM16 or OT_NEAR;
1404 {$else i8086}
1405                         ot:=OT_IMM32 or OT_NEAR;
1406 {$endif i8086}
1407                     end;
1408                 end;
1409               top_local :
1410                 begin
1411                   if (ot and OT_SIZE_MASK)=0 then
1412                     ot:=OT_MEMORY or opsize_2_type[i,opsize]
1413                   else
1414                     ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
1415                 end;
1416               top_const :
1417                 begin
1418                   // if opcode is a SSE or AVX-instruction then we need a
1419                   // special handling (opsize can different from const-size)
1420                   // (e.g. "pextrw  reg/m16, xmmreg, imm8" =>> opsize (16 bit), const-size (8 bit)
1421                   if (InsTabMemRefSizeInfoCache^[opcode].ExistsSSEAVX) and
1422                      (not(InsTabMemRefSizeInfoCache^[opcode].ConstSize in [csiMultiple, csiUnkown])) then
1423                   begin
1424                     case InsTabMemRefSizeInfoCache^[opcode].ConstSize of
1425                       csiNoSize: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE;
1426                         csiMem8: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS8;
1427                        csiMem16: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS16;
1428                        csiMem32: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS32;
1429                        csiMem64: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS64;
1430                     end;
1431                   end
1432                   else
1433                   begin
1434                     { allow 2nd, 3rd or 4th operand being a constant and expect no size for shuf* etc. }
1435                     { further, allow AAD and AAM with imm. operand }
1436                     if (opsize=S_NO) and not((i in [1,2,3])
1437 {$ifndef x86_64}
1438                       or ((i=0) and (opcode in [A_AAD,A_AAM]))
1439 {$endif x86_64}
1440                       ) then
1441                       message(asmr_e_invalid_opcode_and_operand);
1442                     if
1443 {$ifdef i8086}
1444                        (longint(val)>=-128) and (val<=127) then
1445 {$else i8086}
1446                        (opsize<>S_W) and
1447                        (aint(val)>=-128) and (val<=127) then
1448 {$endif not i8086}
1449                       ot:=OT_IMM8 or OT_SIGNED
1450                     else
1451                       ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
1452                     if (val=1) and (i=1) then
1453                       ot := ot or OT_ONENESS;
1454                   end;
1455                 end;
1456               top_none :
1457                 begin
1458                   { generated when there was an error in the
1459                     assembler reader. It never happends when generating
1460                     assembler }
1461                 end;
1462               else
1463                 internalerror(200402266);
1464             end;
1465           end;
1466       end;
1467 
1468 
taicpu.InsEndnull1469     function taicpu.InsEnd:longint;
1470       begin
1471         InsEnd:=InsOffset+InsSize;
1472       end;
1473 
1474 
taicpu.Matchesnull1475       function taicpu.Matches(p:PInsEntry):boolean;
1476       { * IF_SM stands for Size Match: any operand whose size is not
1477        * explicitly specified by the template is `really' intended to be
1478        * the same size as the first size-specified operand.
1479        * Non-specification is tolerated in the input instruction, but
1480        * _wrong_ specification is not.
1481        *
1482        * IF_SM2 invokes Size Match on only the first _two_ operands, for
1483        * three-operand instructions such as SHLD: it implies that the
1484        * first two operands must match in size, but that the third is
1485        * required to be _unspecified_.
1486        *
1487        * IF_SB invokes Size Byte: operands with unspecified size in the
1488        * template are really bytes, and so no non-byte specification in
1489        * the input instruction will be tolerated. IF_SW similarly invokes
1490        * Size Word, and IF_SD invokes Size Doubleword.
1491        *
1492        * (The default state if neither IF_SM nor IF_SM2 is specified is
1493        * that any operand with unspecified size in the template is
1494        * required to have unspecified size in the instruction too...)
1495       }
1496       var
1497         insot,
1498         currot,
1499         i,j,asize,oprs : longint;
1500         insflags:tinsflags;
1501         siz : array[0..max_operands-1] of longint;
1502       begin
1503         result:=false;
1504 
1505         { Check the opcode and operands }
1506         if (p^.opcode<>opcode) or (p^.ops<>ops) then
1507           exit;
1508 
1509 {$ifdef i8086}
1510         { On i8086, we need to skip the i386+ version of Jcc near, if the target
1511           cpu is earlier than 386. There's another entry, later in the table for
1512           i8086, which simulates it with i8086 instructions:
1513             JNcc short +3
1514             JMP near target }
1515         if (p^.opcode=A_Jcc) and (current_settings.cputype<cpu_386) and
1516           (IF_386 in p^.flags) then
1517           exit;
1518 {$endif i8086}
1519 
1520         for i:=0 to p^.ops-1 do
1521          begin
1522            insot:=p^.optypes[i];
1523            currot:=oper[i]^.ot;
1524 
1525            { Check the operand flags }
1526            if (insot and (not currot) and OT_NON_SIZE)<>0 then
1527              exit;
1528            { Check if the passed operand size matches with one of
1529              the supported operand sizes }
1530            if ((insot and OT_SIZE_MASK)<>0) and
1531               ((insot and currot and OT_SIZE_MASK)<>(currot and OT_SIZE_MASK)) then
1532              exit;
1533            { "far" matches only with "far" }
1534            if (insot and OT_FAR)<>(currot and OT_FAR) then
1535              exit;
1536          end;
1537 
1538         { Check operand sizes }
1539         insflags:=p^.flags;
1540         if (insflags*IF_SMASK)<>[] then
1541           begin
1542             { as default an untyped size can get all the sizes, this is different
1543               from nasm, but else we need to do a lot checking which opcodes want
1544               size or not with the automatic size generation }
1545             asize:=-1;
1546             if IF_SB in insflags then
1547               asize:=OT_BITS8
1548             else if IF_SW in insflags then
1549               asize:=OT_BITS16
1550             else if IF_SD in insflags then
1551               asize:=OT_BITS32;
1552             if insflags*IF_ARMASK<>[] then
1553              begin
1554                siz[0]:=-1;
1555                siz[1]:=-1;
1556                siz[2]:=-1;
1557                if IF_AR0 in insflags then
1558                  siz[0]:=asize
1559                else if IF_AR1 in insflags then
1560                  siz[1]:=asize
1561                else if IF_AR2 in insflags then
1562                  siz[2]:=asize
1563                else
1564                  internalerror(2017092101);
1565              end
1566             else
1567              begin
1568                siz[0]:=asize;
1569                siz[1]:=asize;
1570                siz[2]:=asize;
1571              end;
1572 
1573             if insflags*[IF_SM,IF_SM2]<>[] then
1574              begin
1575                if IF_SM2 in insflags then
1576                 oprs:=2
1577                else
1578                 oprs:=p^.ops;
1579                for i:=0 to oprs-1 do
1580                 if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
1581                  begin
1582                    for j:=0 to oprs-1 do
1583                     siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
1584                    break;
1585                  end;
1586               end
1587              else
1588               oprs:=2;
1589 
1590             { Check operand sizes }
1591             for i:=0 to p^.ops-1 do
1592               begin
1593                 insot:=p^.optypes[i];
1594                 currot:=oper[i]^.ot;
1595                 if ((insot and OT_SIZE_MASK)=0) and
1596                    ((currot and OT_SIZE_MASK and (not siz[i]))<>0) and
1597                    { Immediates can always include smaller size }
1598                    ((currot and OT_IMMEDIATE)=0) and
1599                     (((insot and OT_SIZE_MASK) or siz[i])<(currot and OT_SIZE_MASK)) then
1600                   exit;
1601                 if (insot and OT_FAR)<>(currot and OT_FAR) then
1602                   exit;
1603               end;
1604           end;
1605 
1606         if (InsTabMemRefSizeInfoCache^[opcode].MemRefSize in MemRefMultiples) and
1607            (InsTabMemRefSizeInfoCache^[opcode].ExistsSSEAVX) then
1608         begin
1609           for i:=0 to p^.ops-1 do
1610            begin
1611              insot:=p^.optypes[i];
1612              if ((insot and (OT_XMMRM or OT_REG_EXTRA_MASK)) = OT_XMMRM) OR
1613                 ((insot and (OT_YMMRM or OT_REG_EXTRA_MASK)) = OT_YMMRM) then
1614              begin
1615                if (insot and OT_SIZE_MASK) = 0 then
1616                begin
1617                  case insot and (OT_XMMRM or OT_YMMRM or OT_REG_EXTRA_MASK) of
1618                    OT_XMMRM: insot := insot or OT_BITS128;
1619                    OT_YMMRM: insot := insot or OT_BITS256;
1620                  end;
1621                end;
1622              end;
1623 
1624              currot:=oper[i]^.ot;
1625              { Check the operand flags }
1626              if (insot and (not currot) and OT_NON_SIZE)<>0 then
1627                exit;
1628              { Check if the passed operand size matches with one of
1629                the supported operand sizes }
1630              if ((insot and OT_SIZE_MASK)<>0) and
1631                 ((insot and currot and OT_SIZE_MASK)<>(currot and OT_SIZE_MASK)) then
1632                exit;
1633            end;
1634 
1635         end;
1636         result:=true;
1637       end;
1638 
1639 
1640     procedure taicpu.ResetPass1;
1641       begin
1642         { we need to reset everything here, because the choosen insentry
1643           can be invalid for a new situation where the previously optimized
1644           insentry is not correct }
1645         InsEntry:=nil;
1646         InsSize:=0;
1647         LastInsOffset:=-1;
1648       end;
1649 
1650 
1651     procedure taicpu.ResetPass2;
1652       begin
1653         { we are here in a second pass, check if the instruction can be optimized }
1654         if assigned(InsEntry) and
1655            (IF_PASS2 in InsEntry^.flags) then
1656          begin
1657            InsEntry:=nil;
1658            InsSize:=0;
1659          end;
1660         LastInsOffset:=-1;
1661       end;
1662 
1663 
taicpu.CheckIfValidnull1664     function taicpu.CheckIfValid:boolean;
1665       begin
1666         result:=FindInsEntry(nil);
1667       end;
1668 
1669 
taicpu.FindInsentrynull1670     function taicpu.FindInsentry(objdata:TObjData):boolean;
1671       var
1672         i : longint;
1673       begin
1674         result:=false;
1675       { Things which may only be done once, not when a second pass is done to
1676         optimize }
1677         if (Insentry=nil) or (IF_PASS2 in InsEntry^.flags) then
1678          begin
1679            current_filepos:=fileinfo;
1680            { We need intel style operands }
1681            SetOperandOrder(op_intel);
1682            { create the .ot fields }
1683            create_ot(objdata);
1684            { set the file postion }
1685          end
1686         else
1687          begin
1688            { we've already an insentry so it's valid }
1689            result:=true;
1690            exit;
1691          end;
1692         { Lookup opcode in the table }
1693         InsSize:=-1;
1694         i:=instabcache^[opcode];
1695         if i=-1 then
1696          begin
1697            Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
1698            exit;
1699          end;
1700         insentry:=@instab[i];
1701         while (insentry^.opcode=opcode) do
1702          begin
1703            if matches(insentry) then
1704              begin
1705                result:=true;
1706                exit;
1707              end;
1708            inc(insentry);
1709          end;
1710         Message1(asmw_e_invalid_opcode_and_operands,GetString);
1711         { No instruction found, set insentry to nil and inssize to -1 }
1712         insentry:=nil;
1713         inssize:=-1;
1714       end;
1715 
1716 
taicpu.Pass1null1717     function taicpu.Pass1(objdata:TObjData):longint;
1718       begin
1719         Pass1:=0;
1720         { Save the old offset and set the new offset }
1721         InsOffset:=ObjData.CurrObjSec.Size;
1722         { Error? }
1723         if (Insentry=nil) and (InsSize=-1) then
1724           exit;
1725         { set the file postion }
1726         current_filepos:=fileinfo;
1727         { Get InsEntry }
1728         if FindInsEntry(ObjData) then
1729          begin
1730            { Calculate instruction size }
1731            InsSize:=calcsize(insentry);
1732            if segprefix<>NR_NO then
1733             inc(InsSize);
1734            if NeedAddrPrefix then
1735             inc(InsSize);
1736            { Fix opsize if size if forced }
1737            if insentry^.flags*[IF_SB,IF_SW,IF_SD]<>[] then
1738              begin
1739                if insentry^.flags*IF_ARMASK=[] then
1740                  begin
1741                    if IF_SB in insentry^.flags then
1742                      begin
1743                        if opsize=S_NO then
1744                          opsize:=S_B;
1745                      end
1746                    else if IF_SW in insentry^.flags then
1747                      begin
1748                        if opsize=S_NO then
1749                          opsize:=S_W;
1750                      end
1751                    else if IF_SD in insentry^.flags then
1752                      begin
1753                        if opsize=S_NO then
1754                          opsize:=S_L;
1755                      end;
1756                  end;
1757              end;
1758            LastInsOffset:=InsOffset;
1759            Pass1:=InsSize;
1760            exit;
1761          end;
1762         LastInsOffset:=-1;
1763       end;
1764 
1765     const
1766       segprefixes: array[NR_ES..NR_GS] of Byte=(
1767       // es  cs   ss   ds   fs   gs
1768         $26, $2E, $36, $3E, $64, $65
1769       );
1770 
1771     procedure taicpu.Pass2(objdata:TObjData);
1772       begin
1773         { error in pass1 ? }
1774         if insentry=nil then
1775          exit;
1776         current_filepos:=fileinfo;
1777         { Segment override }
1778         if (segprefix>=NR_ES) and (segprefix<=NR_GS) then
1779          begin
1780 {$ifdef i8086}
1781            if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) and
1782               ((segprefix=NR_FS) or (segprefix=NR_GS)) then
1783              Message(asmw_e_instruction_not_supported_by_cpu);
1784 {$endif i8086}
1785            objdata.writebytes(segprefixes[segprefix],1);
1786            { fix the offset for GenNode }
1787            inc(InsOffset);
1788          end
1789         else if segprefix<>NR_NO then
1790           InternalError(201001071);
1791         { Address size prefix? }
1792         if NeedAddrPrefix then
1793         begin
1794           write0x67prefix(objdata);
1795           { fix the offset for GenNode }
1796           inc(InsOffset);
1797         end;
1798         { Generate the instruction }
1799         GenCode(objdata);
1800       end;
1801 
1802 
is_64_bit_refnull1803     function is_64_bit_ref(const ref:treference):boolean;
1804       begin
1805 {$if defined(x86_64)}
1806         result:=not is_32_bit_ref(ref);
1807 {$elseif defined(i386) or defined(i8086)}
1808         result:=false;
1809 {$endif}
1810       end;
1811 
1812 
is_32_bit_refnull1813     function is_32_bit_ref(const ref:treference):boolean;
1814       begin
1815 {$if defined(x86_64)}
1816         result:=(ref.refaddr=addr_no) and
1817                 (ref.base<>NR_RIP) and
1818                 (
1819                  ((ref.index<>NR_NO) and (getsubreg(ref.index)=R_SUBD)) or
1820                  ((ref.base<>NR_NO) and (getsubreg(ref.base)=R_SUBD))
1821                 );
1822 {$elseif defined(i386) or defined(i8086)}
1823         result:=not is_16_bit_ref(ref);
1824 {$endif}
1825       end;
1826 
1827 
is_16_bit_refnull1828     function is_16_bit_ref(const ref:treference):boolean;
1829       var
1830         ir,br : Tregister;
1831         isub,bsub : tsubregister;
1832       begin
1833         if (ref.index<>NR_NO) and (getregtype(ref.index)=R_MMREGISTER) then
1834           exit(false);
1835         ir:=ref.index;
1836         br:=ref.base;
1837         isub:=getsubreg(ir);
1838         bsub:=getsubreg(br);
1839         { it's a direct address }
1840         if (br=NR_NO) and (ir=NR_NO) then
1841           begin
1842             {$ifdef i8086}
1843             result:=true;
1844             {$else i8086}
1845             result:=false;
1846             {$endif}
1847           end
1848         else
1849           { it's an indirection }
1850           begin
1851             result := ((ir<>NR_NO) and (isub=R_SUBW)) or
1852                       ((br<>NR_NO) and (bsub=R_SUBW));
1853           end;
1854       end;
1855 
1856 
get_ref_address_sizenull1857     function get_ref_address_size(const ref:treference):byte;
1858       begin
1859         if is_64_bit_ref(ref) then
1860           result:=64
1861         else if is_32_bit_ref(ref) then
1862           result:=32
1863         else if is_16_bit_ref(ref) then
1864           result:=16
1865         else
1866           internalerror(2017101601);
1867       end;
1868 
1869 
get_default_segment_of_refnull1870     function get_default_segment_of_ref(const ref:treference):tregister;
1871       begin
1872         { for 16-bit registers, we allow base and index to be swapped, that's
1873         why we also we check whether ref.index=NR_BP. For 32-bit registers,
1874         however, index=NR_EBP is encoded differently than base=NR_EBP and has
1875         a different default segment. }
1876         if (ref.base=NR_BP) or (ref.index=NR_BP) or
1877            (ref.base=NR_EBP) or (ref.base=NR_ESP)
1878 {$ifdef x86_64}
1879         or (ref.base=NR_RBP) or (ref.base=NR_RSP)
1880 {$endif x86_64}
1881            then
1882           result:=NR_SS
1883         else
1884           result:=NR_DS;
1885       end;
1886 
1887 
1888     procedure optimize_ref(var ref:treference; inlineasm: boolean);
1889       var
1890         ss_equals_ds: boolean;
1891         tmpreg: TRegister;
1892       begin
1893 {$ifdef x86_64}
1894         { x86_64 in long mode ignores all segment base, limit and access rights
1895           checks for the DS, ES and SS registers, so we can set ss_equals_ds to
1896           true (and thus, perform stronger optimizations on the reference),
1897           regardless of whether this is inline asm or not (so, even if the user
1898           is doing tricks by loading different values into DS and SS, it still
1899           doesn't matter while the processor is in long mode) }
1900         ss_equals_ds:=True;
1901 {$else x86_64}
1902         { for i8086 and i386 inline asm, we assume SS<>DS, even if we're
1903           compiling for a memory model, where SS=DS, because the user might be
1904           doing something tricky with the segment registers (and may have
1905           temporarily set them differently) }
1906         if inlineasm then
1907           ss_equals_ds:=False
1908         else
1909           ss_equals_ds:=segment_regs_equal(NR_DS,NR_SS);
1910 {$endif x86_64}
1911         { remove redundant segment overrides }
1912         if (ref.segment<>NR_NO) and
1913            ((inlineasm and (ref.segment=get_default_segment_of_ref(ref))) or
1914             ((not inlineasm) and (segment_regs_equal(ref.segment,get_default_segment_of_ref(ref))))) then
1915           ref.segment:=NR_NO;
1916         if not is_16_bit_ref(ref) then
1917           begin
1918             { Switching index to base position gives shorter assembler instructions.
1919               Converting index*2 to base+index also gives shorter instructions. }
1920             if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=2) and
1921                (ss_equals_ds or (ref.segment<>NR_NO) or (ref.index<>NR_EBP)) then
1922               begin
1923                 ref.base:=ref.index;
1924                 if ref.scalefactor=2 then
1925                   ref.scalefactor:=1
1926                 else
1927                   begin
1928                     ref.index:=NR_NO;
1929                     ref.scalefactor:=0;
1930                   end;
1931               end;
1932             { Switching rBP+reg to reg+rBP sometimes gives shorter instructions (if there's no offset)
1933               On x86_64 this also works for switching r13+reg to reg+r13. }
1934             if ((ref.base=NR_EBP) {$ifdef x86_64}or (ref.base=NR_RBP) or (ref.base=NR_R13) or (ref.base=NR_R13D){$endif}) and
1935                (ref.index<>NR_NO) and
1936                (ref.index<>NR_EBP) and {$ifdef x86_64}(ref.index<>NR_RBP) and (ref.index<>NR_R13) and (ref.index<>NR_R13D) and{$endif}
1937                (ref.scalefactor<=1) and (ref.offset=0) and (ref.refaddr=addr_no) and
1938                (ss_equals_ds or (ref.segment<>NR_NO)) then
1939               begin
1940                 tmpreg:=ref.base;
1941                 ref.base:=ref.index;
1942                 ref.index:=tmpreg;
1943               end;
1944           end;
1945         { remove redundant segment overrides again }
1946         if (ref.segment<>NR_NO) and
1947            ((inlineasm and (ref.segment=get_default_segment_of_ref(ref))) or
1948             ((not inlineasm) and (segment_regs_equal(ref.segment,get_default_segment_of_ref(ref))))) then
1949           ref.segment:=NR_NO;
1950       end;
1951 
1952 
taicpu.needaddrprefixnull1953     function taicpu.needaddrprefix(opidx:byte):boolean;
1954       begin
1955 {$if defined(x86_64)}
1956         result:=(oper[opidx]^.typ=top_ref) and is_32_bit_ref(oper[opidx]^.ref^);
1957 {$elseif defined(i386)}
1958         result:=(oper[opidx]^.typ=top_ref) and is_16_bit_ref(oper[opidx]^.ref^);
1959 {$elseif defined(i8086)}
1960         result:=(oper[opidx]^.typ=top_ref) and is_32_bit_ref(oper[opidx]^.ref^);
1961 {$endif}
1962       end;
1963 
1964 
taicpu.NeedAddrPrefixnull1965     function taicpu.NeedAddrPrefix:boolean;
1966       var
1967         i: Integer;
1968       begin
1969         for i:=0 to ops-1 do
1970           if needaddrprefix(i) then
1971             exit(true);
1972         result:=false;
1973       end;
1974 
1975 
1976     procedure badreg(r:Tregister);
1977       begin
1978         Message1(asmw_e_invalid_register,generic_regname(r));
1979       end;
1980 
1981 
regvalnull1982     function regval(r:Tregister):byte;
1983       const
1984         intsupreg2opcode: array[0..7] of byte=
1985         // ax cx dx bx si di bp sp   -- in x86reg.dat
1986         // ax cx dx bx sp bp si di   -- needed order
1987           (0, 1, 2, 3, 6, 7, 5, 4);
1988         maxsupreg: array[tregistertype] of tsuperregister=
1989 {$ifdef x86_64}
1990           (0, 16, 9, 8, 16, 32, 0, 0);
1991 {$else x86_64}
1992           (0,  8, 9, 8,  8, 32, 0, 0);
1993 {$endif x86_64}
1994       var
1995         rs: tsuperregister;
1996         rt: tregistertype;
1997       begin
1998         rs:=getsupreg(r);
1999         rt:=getregtype(r);
2000         if (rs>=maxsupreg[rt]) then
2001           badreg(r);
2002         result:=rs and 7;
2003         if (rt=R_INTREGISTER) then
2004           begin
2005             if (rs<8) then
2006               result:=intsupreg2opcode[rs];
2007             if getsubreg(r)=R_SUBH then
2008               inc(result,4);
2009           end;
2010       end;
2011 
2012 
2013 {$if defined(x86_64)}
rexbitsnull2014     function rexbits(r: tregister): byte;
2015       begin
2016         result:=0;
2017         case getregtype(r) of
2018           R_INTREGISTER:
2019             if (getsupreg(r)>=RS_R8) then
2020           { Either B,X or R bits can be set, depending on register role in instruction.
2021             Set all three bits here, caller will discard unnecessary ones. }
2022               result:=result or $47
2023             else if (getsubreg(r)=R_SUBL) and
2024               (getsupreg(r) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
2025               result:=result or $40
2026             else if (getsubreg(r)=R_SUBH) then
2027           { Not an actual REX bit, used to detect incompatible usage of
2028             AH/BH/CH/DH }
2029               result:=result or $80;
2030           R_MMREGISTER:
2031             if getsupreg(r)>=RS_XMM8 then
2032               result:=result or $47;
2033         end;
2034       end;
2035 
process_ea_ref_64_32null2036     function process_ea_ref_64_32(const input:toper;var output:ea;rfield:longint):boolean;
2037       var
2038         sym   : tasmsymbol;
2039         md,s  : byte;
2040         base,index,scalefactor,
2041         o     : longint;
2042         ir,br : Tregister;
2043         isub,bsub : tsubregister;
2044       begin
2045         result:=false;
2046         ir:=input.ref^.index;
2047         br:=input.ref^.base;
2048         isub:=getsubreg(ir);
2049         bsub:=getsubreg(br);
2050         s:=input.ref^.scalefactor;
2051         o:=input.ref^.offset;
2052         sym:=input.ref^.symbol;
2053 
2054         //if ((ir<>NR_NO) and (getregtype(ir)<>R_INTREGISTER)) or
2055         //   ((br<>NR_NO) and (br<>NR_RIP) and (getregtype(br)<>R_INTREGISTER)) then
2056         if ((ir<>NR_NO) and (getregtype(ir)=R_MMREGISTER) and (br<>NR_NO) and (getregtype(br)<>R_INTREGISTER)) or // vector memory (AVX2)
2057            ((ir<>NR_NO) and (getregtype(ir)<>R_INTREGISTER) and (getregtype(ir)<>R_MMREGISTER)) or
2058            ((br<>NR_NO) and (br<>NR_RIP) and (getregtype(br)<>R_INTREGISTER)) then
2059           internalerror(200301081);
2060         { it's direct address }
2061         if (br=NR_NO) and (ir=NR_NO) then
2062          begin
2063            output.sib_present:=true;
2064            output.bytes:=4;
2065            output.modrm:=4 or (rfield shl 3);
2066            output.sib:=$25;
2067          end
2068         else if (br=NR_RIP) and (ir=NR_NO) then
2069           begin
2070             { rip based }
2071             output.sib_present:=false;
2072             output.bytes:=4;
2073             output.modrm:=5 or (rfield shl 3);
2074           end
2075         else
2076         { it's an indirection }
2077          begin
2078            { 16 bit? }
2079 
2080            if ((ir<>NR_NO) and (isub in [R_SUBMMX,R_SUBMMY]) and
2081                (br<>NR_NO) and (bsub=R_SUBQ)
2082               ) then
2083            begin
2084              // vector memory (AVX2) =>> ignore
2085            end
2086            else if ((ir<>NR_NO) and (isub<>R_SUBQ) and (isub<>R_SUBD)) or
2087                    ((br<>NR_NO) and (bsub<>R_SUBQ) and (bsub<>R_SUBD)) then
2088            begin
2089              message(asmw_e_16bit_32bit_not_supported);
2090            end;
2091 
2092            { wrong, for various reasons }
2093            if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
2094             exit;
2095 
2096            output.rex:=output.rex or (rexbits(br) and $F1) or (rexbits(ir) and $F2);
2097            result:=true;
2098 
2099 
2100            { base }
2101            case br of
2102              NR_R8D,
2103              NR_EAX,
2104              NR_R8,
2105              NR_RAX : base:=0;
2106              NR_R9D,
2107              NR_ECX,
2108              NR_R9,
2109              NR_RCX : base:=1;
2110              NR_R10D,
2111              NR_EDX,
2112              NR_R10,
2113              NR_RDX : base:=2;
2114              NR_R11D,
2115              NR_EBX,
2116              NR_R11,
2117              NR_RBX : base:=3;
2118              NR_R12D,
2119              NR_ESP,
2120              NR_R12,
2121              NR_RSP : base:=4;
2122              NR_R13D,
2123              NR_EBP,
2124              NR_R13,
2125              NR_NO,
2126              NR_RBP : base:=5;
2127              NR_R14D,
2128              NR_ESI,
2129              NR_R14,
2130              NR_RSI : base:=6;
2131              NR_R15D,
2132              NR_EDI,
2133              NR_R15,
2134              NR_RDI : base:=7;
2135            else
2136              exit;
2137            end;
2138            { index }
2139            case ir of
2140              NR_R8D,
2141              NR_EAX,
2142              NR_R8,
2143              NR_RAX,
2144              NR_XMM0,
2145              NR_XMM8,
2146              NR_YMM0,
2147              NR_YMM8  : index:=0;
2148              NR_R9D,
2149              NR_ECX,
2150              NR_R9,
2151              NR_RCX,
2152              NR_XMM1,
2153              NR_XMM9,
2154              NR_YMM1,
2155              NR_YMM9  : index:=1;
2156              NR_R10D,
2157              NR_EDX,
2158              NR_R10,
2159              NR_RDX,
2160              NR_XMM2,
2161              NR_XMM10,
2162              NR_YMM2,
2163              NR_YMM10 : index:=2;
2164              NR_R11D,
2165              NR_EBX,
2166              NR_R11,
2167              NR_RBX,
2168              NR_XMM3,
2169              NR_XMM11,
2170              NR_YMM3,
2171              NR_YMM11 : index:=3;
2172              NR_R12D,
2173              NR_ESP,
2174              NR_R12,
2175              NR_NO,
2176              NR_XMM4,
2177              NR_XMM12,
2178              NR_YMM4,
2179              NR_YMM12 : index:=4;
2180              NR_R13D,
2181              NR_EBP,
2182              NR_R13,
2183              NR_RBP,
2184              NR_XMM5,
2185              NR_XMM13,
2186              NR_YMM5,
2187              NR_YMM13: index:=5;
2188              NR_R14D,
2189              NR_ESI,
2190              NR_R14,
2191              NR_RSI,
2192              NR_XMM6,
2193              NR_XMM14,
2194              NR_YMM6,
2195              NR_YMM14: index:=6;
2196              NR_R15D,
2197              NR_EDI,
2198              NR_R15,
2199              NR_RDI,
2200              NR_XMM7,
2201              NR_XMM15,
2202              NR_YMM7,
2203              NR_YMM15: index:=7;
2204            else
2205              exit;
2206            end;
2207            case s of
2208             0,
2209             1 : scalefactor:=0;
2210             2 : scalefactor:=1;
2211             4 : scalefactor:=2;
2212             8 : scalefactor:=3;
2213            else
2214             exit;
2215            end;
2216            { If rbp or r13 is used we must always include an offset }
2217            if (br=NR_NO) or
2218               ((br<>NR_RBP) and (br<>NR_R13) and (br<>NR_EBP) and (br<>NR_R13D) and (o=0) and (sym=nil)) then
2219             md:=0
2220            else
2221             if ((o>=-128) and (o<=127) and (sym=nil)) then
2222              md:=1
2223             else
2224              md:=2;
2225            if (br=NR_NO) or (md=2) then
2226             output.bytes:=4
2227            else
2228             output.bytes:=md;
2229            { SIB needed ? }
2230            if (ir=NR_NO) and (br<>NR_RSP) and (br<>NR_R12) and (br<>NR_ESP) and (br<>NR_R12D)  then
2231             begin
2232               output.sib_present:=false;
2233               output.modrm:=(md shl 6) or (rfield shl 3) or base;
2234             end
2235            else
2236             begin
2237               output.sib_present:=true;
2238               output.modrm:=(md shl 6) or (rfield shl 3) or 4;
2239               output.sib:=(scalefactor shl 6) or (index shl 3) or base;
2240             end;
2241          end;
2242         output.size:=1+ord(output.sib_present)+output.bytes;
2243         result:=true;
2244       end;
2245 
2246 
2247 {$elseif defined(i386) or defined(i8086)}
2248 
process_ea_ref_32null2249     function process_ea_ref_32(const input:toper;out output:ea;rfield:longint):boolean;
2250       var
2251         sym   : tasmsymbol;
2252         md,s  : byte;
2253         base,index,scalefactor,
2254         o     : longint;
2255         ir,br : Tregister;
2256         isub,bsub : tsubregister;
2257       begin
2258         result:=false;
2259         if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)=R_MMREGISTER) and (input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) or // vector memory (AVX2)
2260            ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER) and (getregtype(input.ref^.index)<>R_MMREGISTER)) or
2261            ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
2262          internalerror(200301081);
2263 
2264 
2265         ir:=input.ref^.index;
2266         br:=input.ref^.base;
2267         isub:=getsubreg(ir);
2268         bsub:=getsubreg(br);
2269         s:=input.ref^.scalefactor;
2270         o:=input.ref^.offset;
2271         sym:=input.ref^.symbol;
2272       { it's direct address }
2273         if (br=NR_NO) and (ir=NR_NO) then
2274          begin
2275            { it's a pure offset }
2276            output.sib_present:=false;
2277            output.bytes:=4;
2278            output.modrm:=5 or (rfield shl 3);
2279          end
2280         else
2281         { it's an indirection }
2282          begin
2283            { 16 bit address? }
2284 
2285            if ((ir<>NR_NO) and (isub in [R_SUBMMX,R_SUBMMY]) and
2286                (br<>NR_NO) and (bsub=R_SUBD)
2287               ) then
2288            begin
2289              // vector memory (AVX2) =>> ignore
2290            end
2291            else if ((ir<>NR_NO) and (isub<>R_SUBD)) or
2292                    ((br<>NR_NO) and (bsub<>R_SUBD)) then
2293              message(asmw_e_16bit_not_supported);
2294 {$ifdef OPTEA}
2295            { make single reg base }
2296            if (br=NR_NO) and (s=1) then
2297             begin
2298               br:=ir;
2299               ir:=NR_NO;
2300             end;
2301            { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
2302            if (br=NR_NO) and
2303               (((s=2) and (ir<>NR_ESP)) or
2304                 (s=3) or (s=5) or (s=9)) then
2305             begin
2306               br:=ir;
2307               dec(s);
2308             end;
2309            { swap ESP into base if scalefactor is 1 }
2310            if (s=1) and (ir=NR_ESP) then
2311             begin
2312               ir:=br;
2313               br:=NR_ESP;
2314             end;
2315 {$endif OPTEA}
2316            { wrong, for various reasons }
2317            if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
2318             exit;
2319            { base }
2320            case br of
2321              NR_EAX : base:=0;
2322              NR_ECX : base:=1;
2323              NR_EDX : base:=2;
2324              NR_EBX : base:=3;
2325              NR_ESP : base:=4;
2326              NR_NO,
2327              NR_EBP : base:=5;
2328              NR_ESI : base:=6;
2329              NR_EDI : base:=7;
2330            else
2331              exit;
2332            end;
2333            { index }
2334            case ir of
2335              NR_EAX,
2336              NR_XMM0,
2337              NR_YMM0: index:=0;
2338              NR_ECX,
2339              NR_XMM1,
2340              NR_YMM1: index:=1;
2341              NR_EDX,
2342              NR_XMM2,
2343              NR_YMM2: index:=2;
2344              NR_EBX,
2345              NR_XMM3,
2346              NR_YMM3: index:=3;
2347              NR_NO,
2348              NR_XMM4,
2349              NR_YMM4: index:=4;
2350              NR_EBP,
2351              NR_XMM5,
2352              NR_YMM5: index:=5;
2353              NR_ESI,
2354              NR_XMM6,
2355              NR_YMM6: index:=6;
2356              NR_EDI,
2357              NR_XMM7,
2358              NR_YMM7: index:=7;
2359            else
2360              exit;
2361            end;
2362            case s of
2363             0,
2364             1 : scalefactor:=0;
2365             2 : scalefactor:=1;
2366             4 : scalefactor:=2;
2367             8 : scalefactor:=3;
2368            else
2369             exit;
2370            end;
2371            if (br=NR_NO) or
2372               ((br<>NR_EBP) and (o=0) and (sym=nil)) then
2373             md:=0
2374            else
2375             if ((o>=-128) and (o<=127) and (sym=nil)) then
2376              md:=1
2377             else
2378              md:=2;
2379            if (br=NR_NO) or (md=2) then
2380             output.bytes:=4
2381            else
2382             output.bytes:=md;
2383            { SIB needed ? }
2384            if (ir=NR_NO) and (br<>NR_ESP) then
2385             begin
2386               output.sib_present:=false;
2387               output.modrm:=(longint(md) shl 6) or (rfield shl 3) or base;
2388             end
2389            else
2390             begin
2391               output.sib_present:=true;
2392               output.modrm:=(longint(md) shl 6) or (rfield shl 3) or 4;
2393               output.sib:=(scalefactor shl 6) or (index shl 3) or base;
2394             end;
2395          end;
2396         if output.sib_present then
2397          output.size:=2+output.bytes
2398         else
2399          output.size:=1+output.bytes;
2400         result:=true;
2401       end;
2402 
2403     procedure maybe_swap_index_base(var br,ir:Tregister);
2404       var
2405         tmpreg: Tregister;
2406       begin
2407         if ((br=NR_NO) or (br=NR_SI) or (br=NR_DI)) and
2408            ((ir=NR_NO) or (ir=NR_BP) or (ir=NR_BX)) then
2409           begin
2410             tmpreg:=br;
2411             br:=ir;
2412             ir:=tmpreg;
2413           end;
2414       end;
2415 
process_ea_ref_16null2416     function process_ea_ref_16(const input:toper;out output:ea;rfield:longint):boolean;
2417       var
2418         sym   : tasmsymbol;
2419         md,s,rv  : byte;
2420         base,
2421         o     : longint;
2422         ir,br : Tregister;
2423         isub,bsub : tsubregister;
2424       begin
2425         result:=false;
2426         if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
2427            ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
2428           internalerror(200301081);
2429 
2430 
2431         ir:=input.ref^.index;
2432         br:=input.ref^.base;
2433         isub:=getsubreg(ir);
2434         bsub:=getsubreg(br);
2435         s:=input.ref^.scalefactor;
2436         o:=input.ref^.offset;
2437         sym:=input.ref^.symbol;
2438         { it's a direct address }
2439         if (br=NR_NO) and (ir=NR_NO) then
2440           begin
2441             { it's a pure offset }
2442             output.bytes:=2;
2443             output.modrm:=6 or (rfield shl 3);
2444           end
2445         else
2446           { it's an indirection }
2447           begin
2448             { 32 bit address? }
2449 
2450             if ((ir<>NR_NO) and (isub<>R_SUBW)) or
2451                ((br<>NR_NO) and (bsub<>R_SUBW)) then
2452               message(asmw_e_32bit_not_supported);
2453             { scalefactor can only be 1 in 16-bit addresses }
2454             if (s<>1) and (ir<>NR_NO) then
2455               exit;
2456             maybe_swap_index_base(br,ir);
2457             if (br=NR_BX) and (ir=NR_SI) then
2458               base:=0
2459             else if (br=NR_BX) and (ir=NR_DI) then
2460               base:=1
2461             else if (br=NR_BP) and (ir=NR_SI) then
2462               base:=2
2463             else if (br=NR_BP) and (ir=NR_DI) then
2464               base:=3
2465             else if (br=NR_NO) and (ir=NR_SI) then
2466               base:=4
2467             else if (br=NR_NO) and (ir=NR_DI) then
2468               base:=5
2469             else if (br=NR_BP) and (ir=NR_NO) then
2470               base:=6
2471             else if (br=NR_BX) and (ir=NR_NO) then
2472               base:=7
2473             else
2474               exit;
2475             if (base<>6) and (o=0) and (sym=nil) then
2476               md:=0
2477             else if ((o>=-128) and (o<=127) and (sym=nil)) then
2478               md:=1
2479             else
2480               md:=2;
2481             output.bytes:=md;
2482             output.modrm:=(longint(md) shl 6) or (rfield shl 3) or base;
2483           end;
2484         output.size:=1+output.bytes;
2485         output.sib_present:=false;
2486         result:=true;
2487       end;
2488 {$endif}
2489 
process_eanull2490     function process_ea(const input:toper;out output:ea;rfield:longint):boolean;
2491       var
2492         rv  : byte;
2493       begin
2494         result:=false;
2495         fillchar(output,sizeof(output),0);
2496         {Register ?}
2497         if (input.typ=top_reg) then
2498           begin
2499             rv:=regval(input.reg);
2500             output.modrm:=$c0 or (rfield shl 3) or rv;
2501             output.size:=1;
2502 {$ifdef x86_64}
2503             output.rex:=output.rex or (rexbits(input.reg) and $F1);
2504 {$endif x86_64}
2505             result:=true;
2506             exit;
2507           end;
2508         {No register, so memory reference.}
2509         if input.typ<>top_ref then
2510           internalerror(200409263);
2511 {$if defined(x86_64)}
2512         result:=process_ea_ref_64_32(input,output,rfield);
2513 {$elseif defined(i386) or defined(i8086)}
2514         if is_16_bit_ref(input.ref^) then
2515           result:=process_ea_ref_16(input,output,rfield)
2516         else
2517           result:=process_ea_ref_32(input,output,rfield);
2518 {$endif}
2519       end;
2520 
taicpu.calcsizenull2521     function taicpu.calcsize(p:PInsEntry):shortint;
2522       var
2523         codes : pchar;
2524         c     : byte;
2525         len     : shortint;
2526         ea_data : ea;
2527         exists_vex: boolean;
2528         exists_vex_extension: boolean;
2529         exists_prefix_66: boolean;
2530         exists_prefix_F2: boolean;
2531         exists_prefix_F3: boolean;
2532 {$ifdef x86_64}
2533         omit_rexw : boolean;
2534 {$endif x86_64}
2535       begin
2536         len:=0;
2537         codes:=@p^.code[0];
2538         exists_vex := false;
2539         exists_vex_extension := false;
2540         exists_prefix_66 := false;
2541         exists_prefix_F2 := false;
2542         exists_prefix_F3 := false;
2543 {$ifdef x86_64}
2544         rex:=0;
2545         omit_rexw:=false;
2546 {$endif x86_64}
2547         repeat
2548           c:=ord(codes^);
2549           inc(codes);
2550           case c of
2551             &0 :
2552               break;
2553             &1,&2,&3 :
2554               begin
2555                 inc(codes,c);
2556                 inc(len,c);
2557               end;
2558             &10,&11,&12 :
2559               begin
2560 {$ifdef x86_64}
2561                 rex:=rex or (rexbits(oper[c-&10]^.reg) and $F1);
2562 {$endif x86_64}
2563                 inc(codes);
2564                 inc(len);
2565               end;
2566             &13,&23 :
2567               begin
2568                 inc(codes);
2569                 inc(len);
2570               end;
2571             &4,&5,&6,&7 :
2572               begin
2573                 if opsize={$ifdef i8086}S_L{$else}S_W{$endif} then
2574                   inc(len,2)
2575                 else
2576                   inc(len);
2577               end;
2578             &14,&15,&16,
2579             &20,&21,&22,
2580             &24,&25,&26,&27,
2581             &50,&51,&52 :
2582               inc(len);
2583             &30,&31,&32,
2584             &37,
2585             &60,&61,&62 :
2586               inc(len,2);
2587             &34,&35,&36:
2588               begin
2589 {$ifdef i8086}
2590                 inc(len,2);
2591 {$else i8086}
2592                 if opsize=S_Q then
2593                   inc(len,8)
2594                 else
2595                   inc(len,4);
2596 {$endif i8086}
2597               end;
2598             &44,&45,&46:
2599               inc(len,sizeof(pint));
2600             &54,&55,&56:
2601               inc(len,8);
2602             &40,&41,&42,
2603             &70,&71,&72,
2604             &254,&255,&256 :
2605               inc(len,4);
2606             &64,&65,&66:
2607 {$ifdef i8086}
2608               inc(len,2);
2609 {$else i8086}
2610               inc(len,4);
2611 {$endif i8086}
2612             &74,&75,&76,&77: ; // ignore vex-coded operand-idx
2613             &320,&321,&322 :
2614               begin
2615                 case (oper[c-&320]^.ot and OT_SIZE_MASK) of
2616 {$if defined(i386) or defined(x86_64)}
2617                   OT_BITS16 :
2618 {$elseif defined(i8086)}
2619                   OT_BITS32 :
2620 {$endif}
2621                     inc(len);
2622 {$ifdef x86_64}
2623                   OT_BITS64:
2624                     begin
2625                       rex:=rex or $48;
2626                     end;
2627 {$endif x86_64}
2628                 end;
2629               end;
2630             &310 :
2631 {$if defined(x86_64)}
2632               { every insentry with code 0310 must be marked with NOX86_64 }
2633               InternalError(2011051301);
2634 {$elseif defined(i386)}
2635               inc(len);
2636 {$elseif defined(i8086)}
2637               {nothing};
2638 {$endif}
2639             &311 :
2640 {$if defined(x86_64) or defined(i8086)}
2641               inc(len)
2642 {$endif x86_64 or i8086}
2643               ;
2644             &324 :
2645 {$ifndef i8086}
2646               inc(len)
2647 {$endif not i8086}
2648               ;
2649             &326 :
2650               begin
2651 {$ifdef x86_64}
2652                 rex:=rex or $48;
2653 {$endif x86_64}
2654               end;
2655             &312,
2656             &323,
2657             &327,
2658             &331,&332: ;
2659             &325:
2660 {$ifdef i8086}
2661               inc(len)
2662 {$endif i8086}
2663               ;
2664 
2665             &333:
2666               begin
2667                 inc(len);
2668                 exists_prefix_F2 := true;
2669               end;
2670             &334:
2671               begin
2672                 inc(len);
2673                 exists_prefix_F3 := true;
2674               end;
2675             &361:
2676               begin
2677 {$ifndef i8086}
2678                 inc(len);
2679                 exists_prefix_66 := true;
2680 {$endif not i8086}
2681               end;
2682             &335:
2683 {$ifdef x86_64}
2684               omit_rexw:=true
2685 {$endif x86_64}
2686               ;
2687             &100..&227 :
2688               begin
2689 {$ifdef x86_64}
2690                  if (c<&177) then
2691                   begin
2692                     if (oper[c and 7]^.typ=top_reg) then
2693                       begin
2694                         rex:=rex or (rexbits(oper[c and 7]^.reg) and $F4);
2695                       end;
2696                   end;
2697 
2698 {$endif x86_64}
2699                 if not process_ea(oper[(c shr 3) and 7]^, ea_data, 0) then
2700                   Message(asmw_e_invalid_effective_address)
2701                 else
2702                   inc(len,ea_data.size);
2703 {$ifdef x86_64}
2704                 rex:=rex or ea_data.rex;
2705 {$endif x86_64}
2706 
2707               end;
2708             &362: // VEX prefix for AVX (length = 2 or 3 bytes, dependens on REX.XBW or opcode-prefix ($0F38 or $0F3A))
2709                   // =>> DEFAULT = 2 Bytes
2710               begin
2711                 if not(exists_vex) then
2712                 begin
2713                   inc(len, 2);
2714                   exists_vex := true;
2715                 end;
2716               end;
2717             &363: // REX.W = 1
2718                   // =>> VEX prefix length = 3
2719               begin
2720                 if not(exists_vex_extension) then
2721                 begin
2722                   inc(len);
2723                   exists_vex_extension := true;
2724                 end;
2725               end;
2726             &364: ; // VEX length bit
2727             &366, // operand 2 (ymmreg) encoded immediate byte (bit 4-7)
2728             &367: inc(len); // operand 3 (ymmreg) encoded immediate byte (bit 4-7)
2729             &370: // VEX-Extension prefix $0F
2730                   // ignore for calculating length
2731                   ;
2732             &371, // VEX-Extension prefix $0F38
2733             &372: // VEX-Extension prefix $0F3A
2734               begin
2735                 if not(exists_vex_extension) then
2736                 begin
2737                   inc(len);
2738                   exists_vex_extension := true;
2739                 end;
2740               end;
2741             &300,&301,&302:
2742               begin
2743 {$if defined(x86_64) or defined(i8086)}
2744                 if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
2745                   inc(len);
2746 {$endif x86_64 or i8086}
2747               end;
2748             else
2749              InternalError(200603141);
2750           end;
2751         until false;
2752 {$ifdef x86_64}
2753         if ((rex and $80)<>0) and ((rex and $4F)<>0) then
2754           Message(asmw_e_bad_reg_with_rex);
2755         rex:=rex and $4F;      { reset extra bits in upper nibble }
2756         if omit_rexw then
2757           begin
2758             if rex=$48 then    { remove rex entirely? }
2759               rex:=0
2760             else
2761               rex:=rex and $F7;
2762           end;
2763         if not(exists_vex) then
2764         begin
2765           if rex<>0 then
2766             Inc(len);
2767         end;
2768 {$endif}
2769         if exists_vex then
2770         begin
2771           if exists_prefix_66 then dec(len);
2772           if exists_prefix_F2 then dec(len);
2773           if exists_prefix_F3 then dec(len);
2774 
2775   {$ifdef x86_64}
2776           if not(exists_vex_extension) then
2777             if rex and $0B <> 0 then inc(len);  // REX.WXB <> 0 =>> needed VEX-Extension
2778   {$endif x86_64}
2779 
2780         end;
2781         calcsize:=len;
2782       end;
2783 
2784 
2785     procedure taicpu.write0x66prefix(objdata:TObjData);
2786       const
2787         b66: Byte=$66;
2788       begin
2789 {$ifdef i8086}
2790         if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
2791           Message(asmw_e_instruction_not_supported_by_cpu);
2792 {$endif i8086}
2793         objdata.writebytes(b66,1);
2794       end;
2795 
2796 
2797     procedure taicpu.write0x67prefix(objdata:TObjData);
2798       const
2799         b67: Byte=$67;
2800       begin
2801 {$ifdef i8086}
2802         if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
2803           Message(asmw_e_instruction_not_supported_by_cpu);
2804 {$endif i8086}
2805         objdata.writebytes(b67,1);
2806       end;
2807 
2808 
2809     procedure taicpu.GenCode(objdata:TObjData);
2810       {
2811        * the actual codes (C syntax, i.e. octal):
2812        * \0            - terminates the code. (Unless it's a literal of course.)
2813        * \1, \2, \3    - that many literal bytes follow in the code stream
2814        * \4, \6        - the POP/PUSH (respectively) codes for CS, DS, ES, SS
2815        *                 (POP is never used for CS) depending on operand 0
2816        * \5, \7        - the second byte of POP/PUSH codes for FS, GS, depending
2817        *                 on operand 0
2818        * \10, \11, \12 - a literal byte follows in the code stream, to be added
2819        *                 to the register value of operand 0, 1 or 2
2820        * \13           - a literal byte follows in the code stream, to be added
2821        *                 to the condition code value of the instruction.
2822        * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
2823        * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
2824        * \23           - a literal byte follows in the code stream, to be added
2825        *                 to the inverted condition code value of the instruction
2826        *                 (inverted version of \13).
2827        * \24, \25, \26, \27 - an unsigned byte immediate operand, from operand 0, 1, 2 or 3
2828        * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
2829        * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
2830        *                 assembly mode or the address-size override on the operand
2831        * \37           - a word constant, from the _segment_ part of operand 0
2832        * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
2833        * \44, \45, \46 - select between \3[012], \4[012] or \5[456] depending
2834                          on the address size of instruction
2835        * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
2836        * \54, \55, \56 - a qword immediate, from operand 0, 1 or 2
2837        * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
2838        * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
2839        *                 assembly mode or the address-size override on the operand
2840        * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
2841        * \74, \75, \76 - a vex-coded vector operand, from operand 0, 1 or 2
2842        * \1ab          - a ModRM, calculated on EA in operand a, with the spare
2843        *                 field the register value of operand b.
2844        * \2ab          - a ModRM, calculated on EA in operand a, with the spare
2845        *                 field equal to digit b.
2846        * \254,\255,\256 - a signed 32-bit immediate to be extended to 64 bits
2847        * \300,\301,\302 - might be an 0x67, depending on the address size of
2848        *                 the memory reference in operand x.
2849        * \310          - indicates fixed 16-bit address size, i.e. optional 0x67.
2850        * \311          - indicates fixed 32-bit address size, i.e. optional 0x67.
2851        * \312          - (disassembler only) invalid with non-default address size.
2852        * \320,\321,\322 - might be an 0x66 or 0x48 byte, depending on the operand
2853        *                 size of operand x.
2854        * \324          - indicates fixed 16-bit operand size, i.e. optional 0x66.
2855        * \325          - indicates fixed 32-bit operand size, i.e. optional 0x66.
2856        * \326          - indicates fixed 64-bit operand size, i.e. optional 0x48.
2857        * \327          - indicates that this instruction is only valid when the
2858        *                 operand size is the default (instruction to disassembler,
2859        *                 generates no code in the assembler)
2860        * \331          - instruction not valid with REP prefix.  Hint for
2861        *                 disassembler only; for SSE instructions.
2862        * \332	       - disassemble a rep (0xF3 byte) prefix as repe not rep.
2863        * \333          - 0xF3 prefix for SSE instructions
2864        * \334          - 0xF2 prefix for SSE instructions
2865        * \335          - Indicates 64-bit operand size with REX.W not necessary
2866        * \361          - 0x66 prefix for SSE instructions
2867 
2868        * \362          - VEX prefix for AVX instructions
2869        * \363          - VEX W1
2870        * \364          - VEX Vector length 256
2871        * \366          - operand 2 (ymmreg) encoded in bit 4-7 of the immediate byte
2872        * \367          - operand 3 (ymmreg) encoded in bit 4-7 of the immediate byte
2873 
2874        * \370          - VEX 0F-FLAG
2875        * \371          - VEX 0F38-FLAG
2876        * \372          - VEX 0F3A-FLAG
2877 
2878       }
2879 
2880       var
2881 {$ifdef i8086}
2882         currval : longint;
2883 {$else i8086}
2884         currval : aint;
2885 {$endif i8086}
2886         currsym : tobjsymbol;
2887         currrelreloc,
2888         currabsreloc,
2889         currabsreloc32 : TObjRelocationType;
2890 {$ifdef x86_64}
2891         rexwritten : boolean;
2892 {$endif x86_64}
2893 
2894         procedure getvalsym(opidx:longint);
2895           begin
2896             case oper[opidx]^.typ of
2897               top_ref :
2898                 begin
2899                   currval:=oper[opidx]^.ref^.offset;
2900                   currsym:=ObjData.symbolref(oper[opidx]^.ref^.symbol);
2901 {$ifdef i8086}
2902                   if oper[opidx]^.ref^.refaddr=addr_seg then
2903                     begin
2904                       currrelreloc:=RELOC_SEGREL;
2905                       currabsreloc:=RELOC_SEG;
2906                       currabsreloc32:=RELOC_SEG;
2907                     end
2908                   else if oper[opidx]^.ref^.refaddr=addr_dgroup then
2909                     begin
2910                       currrelreloc:=RELOC_DGROUPREL;
2911                       currabsreloc:=RELOC_DGROUP;
2912                       currabsreloc32:=RELOC_DGROUP;
2913                     end
2914                   else if oper[opidx]^.ref^.refaddr=addr_fardataseg then
2915                     begin
2916                       currrelreloc:=RELOC_FARDATASEGREL;
2917                       currabsreloc:=RELOC_FARDATASEG;
2918                       currabsreloc32:=RELOC_FARDATASEG;
2919                     end
2920                   else
2921 {$endif i8086}
2922 {$ifdef i386}
2923                   if (oper[opidx]^.ref^.refaddr=addr_pic) and
2924                      (tf_pic_uses_got in target_info.flags) then
2925                     begin
2926                       currrelreloc:=RELOC_PLT32;
2927                       currabsreloc:=RELOC_GOT32;
2928                       currabsreloc32:=RELOC_GOT32;
2929                     end
2930                   else
2931 {$endif i386}
2932 {$ifdef x86_64}
2933                   if oper[opidx]^.ref^.refaddr=addr_pic then
2934                     begin
2935                       currrelreloc:=RELOC_PLT32;
2936                       currabsreloc:=RELOC_GOTPCREL;
2937                       currabsreloc32:=RELOC_GOTPCREL;
2938                     end
2939                   else if oper[opidx]^.ref^.refaddr=addr_pic_no_got then
2940                     begin
2941                       currrelreloc:=RELOC_RELATIVE;
2942                       currabsreloc:=RELOC_RELATIVE;
2943                       currabsreloc32:=RELOC_RELATIVE;
2944                     end
2945                   else
2946 {$endif x86_64}
2947                     begin
2948                       currrelreloc:=RELOC_RELATIVE;
2949                       currabsreloc:=RELOC_ABSOLUTE;
2950                       currabsreloc32:=RELOC_ABSOLUTE32;
2951                     end;
2952                 end;
2953               top_const :
2954                 begin
2955 {$ifdef i8086}
2956                   currval:=longint(oper[opidx]^.val);
2957 {$else i8086}
2958                   currval:=aint(oper[opidx]^.val);
2959 {$endif i8086}
2960                   currsym:=nil;
2961                   currabsreloc:=RELOC_ABSOLUTE;
2962                   currabsreloc32:=RELOC_ABSOLUTE32;
2963                 end;
2964               else
2965                 Message(asmw_e_immediate_or_reference_expected);
2966             end;
2967           end;
2968 
2969 {$ifdef x86_64}
2970        procedure maybewriterex;
2971        begin
2972           if (rex<>0) and not(rexwritten) then
2973             begin
2974               rexwritten:=true;
2975               objdata.writebytes(rex,1);
2976             end;
2977         end;
2978 {$endif x86_64}
2979 
2980        procedure objdata_writereloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
2981          begin
2982 {$ifdef i386}
2983                { Special case of '_GLOBAL_OFFSET_TABLE_'
2984                  which needs a special relocation type R_386_GOTPC }
2985                if assigned (p) and
2986                   (p.name='_GLOBAL_OFFSET_TABLE_') and
2987                   (tf_pic_uses_got in target_info.flags) then
2988                  begin
2989                    { nothing else than a 4 byte relocation should occur
2990                      for GOT }
2991                    if len<>4 then
2992                      Message1(asmw_e_invalid_opcode_and_operands,GetString);
2993                    Reloctype:=RELOC_GOTPC;
2994                    { We need to add the offset of the relocation
2995                      of _GLOBAL_OFFSET_TABLE symbol within
2996                      the current instruction }
2997                    inc(data,objdata.currobjsec.size-insoffset);
2998                  end;
2999 {$endif i386}
3000            objdata.writereloc(data,len,p,Reloctype);
3001          end;
3002 
3003 
3004       const
3005         CondVal:array[TAsmCond] of byte=($0,
3006          $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
3007          $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
3008          $0, $A, $A, $B, $8, $4);
3009       var
3010         c : byte;
3011         pb : pbyte;
3012         codes : pchar;
3013         bytes : array[0..3] of byte;
3014         rfield,
3015         data,s,opidx : longint;
3016         ea_data : ea;
3017         relsym : TObjSymbol;
3018         needed_VEX_Extension: boolean;
3019         needed_VEX: boolean;
3020         opmode: integer;
3021         VEXvvvv: byte;
3022         VEXmmmmm: byte;
3023       begin
3024         { safety check }
3025         if objdata.currobjsec.size<>longword(insoffset) then
3026            internalerror(200130121);
3027 
3028         { those variables are initialized inside local procedures, the dfa cannot handle this yet }
3029         currsym:=nil;
3030         currabsreloc:=RELOC_NONE;
3031         currabsreloc32:=RELOC_NONE;
3032         currrelreloc:=RELOC_NONE;
3033         currval:=0;
3034 
3035         { check instruction's processor level }
3036         { todo: maybe adapt and enable this code for i386 and x86_64 as well }
3037 {$ifdef i8086}
3038         if objdata.CPUType<>cpu_none then
3039           begin
3040             if IF_8086 in insentry^.flags then
3041             else if IF_186 in insentry^.flags then
3042               begin
3043                 if objdata.CPUType<cpu_186 then
3044                   Message(asmw_e_instruction_not_supported_by_cpu);
3045               end
3046             else if IF_286 in insentry^.flags then
3047               begin
3048                 if objdata.CPUType<cpu_286 then
3049                   Message(asmw_e_instruction_not_supported_by_cpu);
3050               end
3051             else if IF_386 in insentry^.flags then
3052               begin
3053                 if objdata.CPUType<cpu_386 then
3054                   Message(asmw_e_instruction_not_supported_by_cpu);
3055               end
3056             else if IF_486 in insentry^.flags then
3057               begin
3058                 if objdata.CPUType<cpu_486 then
3059                   Message(asmw_e_instruction_not_supported_by_cpu);
3060               end
3061             else if IF_PENT in insentry^.flags then
3062               begin
3063                 if objdata.CPUType<cpu_Pentium then
3064                   Message(asmw_e_instruction_not_supported_by_cpu);
3065               end
3066             else if IF_P6 in insentry^.flags then
3067               begin
3068                 if objdata.CPUType<cpu_Pentium2 then
3069                   Message(asmw_e_instruction_not_supported_by_cpu);
3070               end
3071             else if IF_KATMAI in insentry^.flags then
3072               begin
3073                 if objdata.CPUType<cpu_Pentium3 then
3074                   Message(asmw_e_instruction_not_supported_by_cpu);
3075               end
3076             else if insentry^.flags*[IF_WILLAMETTE,IF_PRESCOTT]<>[] then
3077               begin
3078                 if objdata.CPUType<cpu_Pentium4 then
3079                   Message(asmw_e_instruction_not_supported_by_cpu);
3080               end
3081             else if IF_NEC in insentry^.flags then
3082               begin
3083               { the NEC V20/V30 extensions are incompatible with 386+, due to overlapping opcodes }
3084                 if objdata.CPUType>=cpu_386 then
3085                   Message(asmw_e_instruction_not_supported_by_cpu);
3086               end
3087             else if IF_SANDYBRIDGE in insentry^.flags then
3088               begin
3089               { todo: handle these properly }
3090             end;
3091           end;
3092 {$endif i8086}
3093 
3094         { load data to write }
3095         codes:=insentry^.code;
3096 {$ifdef x86_64}
3097         rexwritten:=false;
3098 {$endif x86_64}
3099         { Force word push/pop for registers }
3100         if (opsize={$ifdef i8086}S_L{$else}S_W{$endif}) and ((codes[0]=#4) or (codes[0]=#6) or
3101             ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
3102           write0x66prefix(objdata);
3103 
3104         // needed VEX Prefix (for AVX etc.)
3105 
3106         needed_VEX := false;
3107         needed_VEX_Extension := false;
3108         opmode   := -1;
3109         VEXvvvv  := 0;
3110         VEXmmmmm := 0;
3111         repeat
3112           c:=ord(codes^);
3113           inc(codes);
3114 
3115           case c of
3116              &0: break;
3117              &1,
3118              &2,
3119              &3: inc(codes,c);
3120             &74: opmode := 0;
3121             &75: opmode := 1;
3122             &76: opmode := 2;
3123            &333: VEXvvvv                := VEXvvvv  OR $02; // set SIMD-prefix $F3
3124            &334: VEXvvvv                := VEXvvvv  OR $03; // set SIMD-prefix $F2
3125            &361: VEXvvvv                := VEXvvvv  OR $01; // set SIMD-prefix $66
3126            &362: needed_VEX             := true;
3127            &363: begin
3128                    needed_VEX_Extension := true;
3129                    VEXvvvv              := VEXvvvv  OR (1 shl 7); // set REX.W
3130                  end;
3131            &364: VEXvvvv                := VEXvvvv  OR $04; // vectorlength = 256 bits AND no scalar
3132            &370: VEXmmmmm               := VEXmmmmm OR $01; // set leading opcode byte $0F
3133            &371: begin
3134                    needed_VEX_Extension := true;
3135                    VEXmmmmm             := VEXmmmmm OR $02; // set leading opcode byte $0F38
3136                  end;
3137            &372: begin
3138                    needed_VEX_Extension := true;
3139                    VEXmmmmm             := VEXmmmmm OR $03; // set leading opcode byte $0F3A
3140                  end;
3141 
3142           end;
3143         until false;
3144 
3145         if needed_VEX then
3146         begin
3147           if (opmode > ops) or
3148              (opmode < -1) then
3149           begin
3150             Internalerror(777100);
3151           end
3152           else if opmode = -1 then
3153           begin
3154             VEXvvvv := VEXvvvv or ($0F shl 3); // set VEXvvvv bits (bits 6-3) to 1
3155           end
3156           else if oper[opmode]^.typ = top_reg then
3157           begin
3158             VEXvvvv := VEXvvvv or ((not(regval(oper[opmode]^.reg)) and $07) shl 3);
3159 
3160             {$ifdef x86_64}
3161               if rexbits(oper[opmode]^.reg) = 0 then VEXvvvv := VEXvvvv or (1 shl 6);
3162             {$else}
3163               VEXvvvv := VEXvvvv or (1 shl 6);
3164             {$endif x86_64}
3165           end
3166           else Internalerror(777101);
3167 
3168           if not(needed_VEX_Extension) then
3169           begin
3170             {$ifdef x86_64}
3171               if rex and $0B <> 0 then needed_VEX_Extension := true;
3172             {$endif x86_64}
3173           end;
3174 
3175           if needed_VEX_Extension then
3176           begin
3177             // VEX-Prefix-Length = 3 Bytes
3178             {$ifdef x86_64}
3179               VEXmmmmm := VEXmmmmm or ((not(rex) and $07) shl 5);  // set REX.rxb
3180               VEXvvvv  := VEXvvvv or ((rex and $08) shl 7);        // set REX.w
3181             {$else}
3182               VEXmmmmm := VEXmmmmm or (7 shl 5);  //
3183             {$endif x86_64}
3184 
3185             bytes[0]:=$C4;
3186             bytes[1]:=VEXmmmmm;
3187             bytes[2]:=VEXvvvv;
3188             objdata.writebytes(bytes,3);
3189           end
3190           else
3191           begin
3192             // VEX-Prefix-Length = 2 Bytes
3193             {$ifdef x86_64}
3194               if rex and $04 = 0 then
3195             {$endif x86_64}
3196             begin
3197               VEXvvvv := VEXvvvv or (1 shl 7);
3198             end;
3199 
3200             bytes[0]:=$C5;
3201             bytes[1]:=VEXvvvv;
3202             objdata.writebytes(bytes,2);
3203           end;
3204         end
3205         else
3206         begin
3207           needed_VEX_Extension := false;
3208           opmode := -1;
3209         end;
3210 
3211         { load data to write }
3212         codes:=insentry^.code;
3213 
3214         repeat
3215           c:=ord(codes^);
3216           inc(codes);
3217           case c of
3218             &0 :
3219               break;
3220             &1,&2,&3 :
3221               begin
3222 {$ifdef x86_64}
3223                 if not(needed_VEX) then  // TG
3224                   maybewriterex;
3225 {$endif x86_64}
3226                 objdata.writebytes(codes^,c);
3227                 inc(codes,c);
3228               end;
3229             &4,&6 :
3230               begin
3231                 case oper[0]^.reg of
3232                   NR_CS:
3233                     bytes[0]:=$e;
3234                   NR_NO,
3235                   NR_DS:
3236                     bytes[0]:=$1e;
3237                   NR_ES:
3238                     bytes[0]:=$6;
3239                   NR_SS:
3240                     bytes[0]:=$16;
3241                   else
3242                     internalerror(777004);
3243                 end;
3244                 if c=&4 then
3245                   inc(bytes[0]);
3246                 objdata.writebytes(bytes,1);
3247               end;
3248             &5,&7 :
3249               begin
3250                 case oper[0]^.reg of
3251                   NR_FS:
3252                     bytes[0]:=$a0;
3253                   NR_GS:
3254                     bytes[0]:=$a8;
3255                   else
3256                     internalerror(777005);
3257                 end;
3258                 if c=&5 then
3259                   inc(bytes[0]);
3260                 objdata.writebytes(bytes,1);
3261               end;
3262             &10,&11,&12 :
3263               begin
3264 {$ifdef x86_64}
3265                 if not(needed_VEX) then  // TG
3266                   maybewriterex;
3267 {$endif x86_64}
3268                 bytes[0]:=ord(codes^)+regval(oper[c-&10]^.reg);
3269                 inc(codes);
3270                 objdata.writebytes(bytes,1);
3271               end;
3272             &13 :
3273               begin
3274                 bytes[0]:=ord(codes^)+condval[condition];
3275                 inc(codes);
3276                 objdata.writebytes(bytes,1);
3277               end;
3278             &14,&15,&16 :
3279               begin
3280                 getvalsym(c-&14);
3281                 if (currval<-128) or (currval>127) then
3282                  Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
3283                 if assigned(currsym) then
3284                   objdata_writereloc(currval,1,currsym,currabsreloc)
3285                 else
3286                   objdata.writebytes(currval,1);
3287               end;
3288             &20,&21,&22 :
3289               begin
3290                 getvalsym(c-&20);
3291                 if (currval<-256) or (currval>255) then
3292                  Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
3293                 if assigned(currsym) then
3294                  objdata_writereloc(currval,1,currsym,currabsreloc)
3295                 else
3296                  objdata.writebytes(currval,1);
3297               end;
3298             &23 :
3299               begin
3300                 bytes[0]:=ord(codes^)+condval[inverse_cond(condition)];
3301                 inc(codes);
3302                 objdata.writebytes(bytes,1);
3303               end;
3304             &24,&25,&26,&27 :
3305               begin
3306                 getvalsym(c-&24);
3307                 if IF_IMM3 in insentry^.flags then
3308                   begin
3309                     if (currval<0) or (currval>7) then
3310                       Message2(asmw_e_value_exceeds_bounds,'unsigned triad',tostr(currval));
3311                   end
3312                 else if IF_IMM4 in insentry^.flags then
3313                   begin
3314                     if (currval<0) or (currval>15) then
3315                       Message2(asmw_e_value_exceeds_bounds,'unsigned nibble',tostr(currval));
3316                   end
3317                 else
3318                   if (currval<0) or (currval>255) then
3319                     Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
3320                 if assigned(currsym) then
3321                  objdata_writereloc(currval,1,currsym,currabsreloc)
3322                 else
3323                  objdata.writebytes(currval,1);
3324               end;
3325             &30,&31,&32 :     // 030..032
3326               begin
3327                 getvalsym(c-&30);
3328 {$ifndef i8086}
3329                 { currval is an aint so this cannot happen on i8086 and causes only a warning }
3330                 if (currval<-65536) or (currval>65535) then
3331                  Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
3332 {$endif i8086}
3333                 if assigned(currsym)
3334 {$ifdef i8086}
3335                    or (currabsreloc in [RELOC_DGROUP,RELOC_FARDATASEG])
3336 {$endif i8086}
3337                 then
3338                  objdata_writereloc(currval,2,currsym,currabsreloc)
3339                 else
3340                  objdata.writebytes(currval,2);
3341               end;
3342             &34,&35,&36 :     // 034..036
3343               { !!! These are intended (and used in opcode table) to select depending
3344                     on address size, *not* operand size. Works by coincidence only. }
3345               begin
3346                 getvalsym(c-&34);
3347 {$ifdef i8086}
3348                 if assigned(currsym) then
3349                   objdata_writereloc(currval,2,currsym,currabsreloc)
3350                 else
3351                   objdata.writebytes(currval,2);
3352 {$else i8086}
3353                 if opsize=S_Q then
3354                   begin
3355                     if assigned(currsym) then
3356                      objdata_writereloc(currval,8,currsym,currabsreloc)
3357                     else
3358                      objdata.writebytes(currval,8);
3359                   end
3360                 else
3361                   begin
3362                     if assigned(currsym) then
3363                       objdata_writereloc(currval,4,currsym,currabsreloc32)
3364                     else
3365                       objdata.writebytes(currval,4);
3366                   end
3367 {$endif i8086}
3368               end;
3369             &40,&41,&42 :    // 040..042
3370               begin
3371                 getvalsym(c-&40);
3372                 if assigned(currsym)
3373 {$ifdef i8086}
3374                    or (currabsreloc in [RELOC_DGROUP,RELOC_FARDATASEG])
3375 {$endif i8086}
3376                 then
3377                  objdata_writereloc(currval,4,currsym,currabsreloc32)
3378                 else
3379                  objdata.writebytes(currval,4);
3380               end;
3381             &44,&45,&46 :// 044..046 - select between word/dword/qword depending on
3382               begin      // address size (we support only default address sizes).
3383                 getvalsym(c-&44);
3384 {$if defined(x86_64)}
3385                 if assigned(currsym) then
3386                   objdata_writereloc(currval,8,currsym,currabsreloc)
3387                 else
3388                   objdata.writebytes(currval,8);
3389 {$elseif defined(i386)}
3390                 if assigned(currsym) then
3391                   objdata_writereloc(currval,4,currsym,currabsreloc32)
3392                 else
3393                   objdata.writebytes(currval,4);
3394 {$elseif defined(i8086)}
3395                 if assigned(currsym) then
3396                   objdata_writereloc(currval,2,currsym,currabsreloc)
3397                 else
3398                   objdata.writebytes(currval,2);
3399 {$endif}
3400               end;
3401             &50,&51,&52 :   // 050..052 - byte relative operand
3402               begin
3403                 getvalsym(c-&50);
3404                 data:=currval-insend;
3405 {$push}
3406 {$r-,q-} { disable also overflow as address returns a qword for x86_64 }
3407                 if assigned(currsym) then
3408                  inc(data,currsym.address);
3409 {$pop}
3410                 if (data>127) or (data<-128) then
3411                  Message1(asmw_e_short_jmp_out_of_range,tostr(data));
3412                 objdata.writebytes(data,1);
3413               end;
3414             &54,&55,&56:   // 054..056 - qword immediate operand
3415               begin
3416                 getvalsym(c-&54);
3417                 if assigned(currsym) then
3418                   objdata_writereloc(currval,8,currsym,currabsreloc)
3419                 else
3420                   objdata.writebytes(currval,8);
3421               end;
3422             &60,&61,&62 :
3423               begin
3424                 getvalsym(c-&60);
3425 {$ifdef i8086}
3426                 if assigned(currsym) then
3427                  objdata_writereloc(currval,2,currsym,currrelreloc)
3428                 else
3429                  objdata_writereloc(currval-insend,2,nil,currabsreloc)
3430 {$else i8086}
3431                 InternalError(777006);
3432 {$endif i8086}
3433               end;
3434             &64,&65,&66 :  // 064..066 - select between 16/32 address mode, but we support only 32 (only 16 on i8086)
3435               begin
3436                 getvalsym(c-&64);
3437 {$ifdef i8086}
3438                 if assigned(currsym) then
3439                  objdata_writereloc(currval,2,currsym,currrelreloc)
3440                 else
3441                  objdata_writereloc(currval-insend,2,nil,currabsreloc)
3442 {$else i8086}
3443                 if assigned(currsym) then
3444                  objdata_writereloc(currval,4,currsym,currrelreloc)
3445                 else
3446                  objdata_writereloc(currval-insend,4,nil,currabsreloc32)
3447 {$endif i8086}
3448               end;
3449             &70,&71,&72 :  // 070..072 - long relative operand
3450               begin
3451                 getvalsym(c-&70);
3452                 if assigned(currsym) then
3453                  objdata_writereloc(currval,4,currsym,currrelreloc)
3454                 else
3455                  objdata_writereloc(currval-insend,4,nil,currabsreloc32)
3456               end;
3457             &74,&75,&76 : ; // 074..076 - vex-coded vector operand
3458                             // ignore
3459             &254,&255,&256 :  // 0254..0256 - dword implicitly sign-extended to 64-bit (x86_64 only)
3460               begin
3461                 getvalsym(c-&254);
3462 {$ifdef x86_64}
3463                 { for i386 as aint type is longint the
3464                   following test is useless }
3465                 if (currval<low(longint)) or (currval>high(longint)) then
3466                   Message2(asmw_e_value_exceeds_bounds,'signed dword',tostr(currval));
3467 {$endif x86_64}
3468 
3469                 if assigned(currsym) then
3470                   objdata_writereloc(currval,4,currsym,currabsreloc32)
3471                 else
3472                   objdata.writebytes(currval,4);
3473               end;
3474             &300,&301,&302:
3475               begin
3476 {$if defined(x86_64) or defined(i8086)}
3477                 if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
3478                   write0x67prefix(objdata);
3479 {$endif x86_64 or i8086}
3480               end;
3481             &310 :   { fixed 16-bit addr }
3482 {$if defined(x86_64)}
3483               { every insentry having code 0310 must be marked with NOX86_64 }
3484               InternalError(2011051302);
3485 {$elseif defined(i386)}
3486               write0x67prefix(objdata);
3487 {$elseif defined(i8086)}
3488               {nothing};
3489 {$endif}
3490             &311 :   { fixed 32-bit addr }
3491 {$if defined(x86_64) or defined(i8086)}
3492               write0x67prefix(objdata)
3493 {$endif x86_64 or i8086}
3494               ;
3495             &320,&321,&322 :
3496               begin
3497                 case oper[c-&320]^.ot and OT_SIZE_MASK of
3498 {$if defined(i386) or defined(x86_64)}
3499                   OT_BITS16 :
3500 {$elseif defined(i8086)}
3501                   OT_BITS32 :
3502 {$endif}
3503                     write0x66prefix(objdata);
3504 {$ifndef x86_64}
3505                   OT_BITS64 :
3506                       Message(asmw_e_64bit_not_supported);
3507 {$endif x86_64}
3508                 end;
3509               end;
3510             &323 : {no action needed};
3511             &325:
3512 {$ifdef i8086}
3513               write0x66prefix(objdata);
3514 {$else i8086}
3515               {no action needed};
3516 {$endif i8086}
3517 
3518             &324,
3519             &361:
3520               begin
3521 {$ifndef i8086}
3522                 if not(needed_VEX) then
3523                   write0x66prefix(objdata);
3524 {$endif not i8086}
3525               end;
3526             &326 :
3527               begin
3528 {$ifndef x86_64}
3529                 Message(asmw_e_64bit_not_supported);
3530 {$endif x86_64}
3531               end;
3532             &333 :
3533               begin
3534                 if not(needed_VEX) then
3535                 begin
3536                   bytes[0]:=$f3;
3537                   objdata.writebytes(bytes,1);
3538                 end;
3539               end;
3540             &334 :
3541               begin
3542                 if not(needed_VEX) then
3543                 begin
3544                   bytes[0]:=$f2;
3545                   objdata.writebytes(bytes,1);
3546                 end;
3547               end;
3548             &335:
3549               ;
3550             &312,
3551             &327,
3552             &331,&332 :
3553               begin
3554                 { these are dissambler hints or 32 bit prefixes which
3555                   are not needed }
3556               end;
3557             &362..&364: ; // VEX flags =>> nothing todo
3558             &366, &367:
3559               begin
3560                 opidx:=c-&364;  { 0366->operand 2, 0367->operand 3 }
3561                 if needed_VEX and
3562                   (ops=4) and
3563                   (oper[opidx]^.typ=top_reg) and
3564                   ((oper[opidx]^.ot and OT_REG_EXTRA_MASK)=otf_reg_xmm) or
3565                   ((oper[opidx]^.ot and OT_REG_EXTRA_MASK)=otf_reg_ymm) then
3566                   begin
3567                     bytes[0] := ((getsupreg(oper[opidx]^.reg) and 15) shl 4);
3568                     objdata.writebytes(bytes,1);
3569                   end
3570                 else
3571                   Internalerror(2014032001);
3572               end;
3573             &370..&372: ; // VEX flags =>> nothing todo
3574             &37:
3575               begin
3576 {$ifdef i8086}
3577                 if assigned(currsym) then
3578                   objdata_writereloc(0,2,currsym,RELOC_SEG)
3579                 else
3580                   InternalError(2015041503);
3581 {$else i8086}
3582                 InternalError(777006);
3583 {$endif i8086}
3584               end;
3585             else
3586               begin
3587                 { rex should be written at this point }
3588 {$ifdef x86_64}
3589                 if not(needed_VEX) then  // TG
3590                   if (rex<>0) and not(rexwritten) then
3591                     internalerror(200603191);
3592 {$endif x86_64}
3593                 if (c>=&100) and (c<=&227) then  // 0100..0227
3594                  begin
3595                    if (c<&177) then            // 0177
3596                     begin
3597                       if (oper[c and 7]^.typ=top_reg) then
3598                         rfield:=regval(oper[c and 7]^.reg)
3599                       else
3600                         rfield:=regval(oper[c and 7]^.ref^.base);
3601                     end
3602                    else
3603                     rfield:=c and 7;
3604                    opidx:=(c shr 3) and 7;
3605                    if not process_ea(oper[opidx]^,ea_data,rfield) then
3606                      Message(asmw_e_invalid_effective_address);
3607 
3608                    pb:=@bytes[0];
3609                    pb^:=ea_data.modrm;
3610                    inc(pb);
3611                    if ea_data.sib_present then
3612                     begin
3613                       pb^:=ea_data.sib;
3614                       inc(pb);
3615                     end;
3616 
3617                    s:=pb-@bytes[0];
3618                    objdata.writebytes(bytes,s);
3619 
3620                    case ea_data.bytes of
3621                      0 : ;
3622                      1 :
3623                        begin
3624                          if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
3625                            begin
3626                              currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
3627 {$ifdef i386}
3628                              if (oper[opidx]^.ref^.refaddr=addr_pic) and
3629                                 (tf_pic_uses_got in target_info.flags) then
3630                                currabsreloc:=RELOC_GOT32
3631                              else
3632 {$endif i386}
3633 {$ifdef x86_64}
3634                              if oper[opidx]^.ref^.refaddr=addr_pic then
3635                                currabsreloc:=RELOC_GOTPCREL
3636                              else
3637 {$endif x86_64}
3638                                currabsreloc:=RELOC_ABSOLUTE;
3639                              objdata_writereloc(oper[opidx]^.ref^.offset,1,currsym,currabsreloc);
3640                            end
3641                          else
3642                           begin
3643                             bytes[0]:=oper[opidx]^.ref^.offset;
3644                             objdata.writebytes(bytes,1);
3645                           end;
3646                          inc(s);
3647                        end;
3648                      2,4 :
3649                        begin
3650                          currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
3651                          currval:=oper[opidx]^.ref^.offset;
3652 {$ifdef x86_64}
3653                          if oper[opidx]^.ref^.refaddr=addr_pic then
3654                            currabsreloc:=RELOC_GOTPCREL
3655                          else
3656                            if oper[opidx]^.ref^.base=NR_RIP then
3657                              begin
3658                                currabsreloc:=RELOC_RELATIVE;
3659                                { Adjust reloc value by number of bytes following the displacement,
3660                                  but not if displacement is specified by literal constant }
3661                                if Assigned(currsym) then
3662                                  Dec(currval,InsEnd-objdata.CurrObjSec.Size-ea_data.bytes);
3663                              end
3664                            else
3665 {$endif x86_64}
3666 {$ifdef i386}
3667                          if (oper[opidx]^.ref^.refaddr=addr_pic) and
3668                             (tf_pic_uses_got in target_info.flags) then
3669                            currabsreloc:=RELOC_GOT32
3670                          else
3671 {$endif i386}
3672 {$ifdef i8086}
3673                          if ea_data.bytes=2 then
3674                            currabsreloc:=RELOC_ABSOLUTE
3675                          else
3676 {$endif i8086}
3677                              currabsreloc:=RELOC_ABSOLUTE32;
3678 
3679                            if (currabsreloc in [RELOC_ABSOLUTE32{$ifdef i8086},RELOC_ABSOLUTE{$endif}]) and
3680                             (Assigned(oper[opidx]^.ref^.relsymbol)) then
3681                            begin
3682                              relsym:=objdata.symbolref(oper[opidx]^.ref^.relsymbol);
3683                              if relsym.objsection=objdata.CurrObjSec then
3684                                begin
3685                                  currval:=objdata.CurrObjSec.size+ea_data.bytes-relsym.offset+currval;
3686 {$ifdef i8086}
3687                                  if ea_data.bytes=4 then
3688                                    currabsreloc:=RELOC_RELATIVE32
3689                                  else
3690 {$endif i8086}
3691                                    currabsreloc:=RELOC_RELATIVE;
3692                                end
3693                              else
3694                                begin
3695                                  currabsreloc:=RELOC_PIC_PAIR;
3696                                  currval:=relsym.offset;
3697                                end;
3698                            end;
3699                          objdata_writereloc(currval,ea_data.bytes,currsym,currabsreloc);
3700                          inc(s,ea_data.bytes);
3701                        end;
3702                    end;
3703                  end
3704                 else
3705                  InternalError(777007);
3706               end;
3707           end;
3708         until false;
3709       end;
3710 
3711 
taicpu.is_same_reg_movenull3712     function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
3713       begin
3714         result:=(((opcode=A_MOV) or (opcode=A_XCHG)) and
3715                  (regtype = R_INTREGISTER) and
3716                  (ops=2) and
3717                  (oper[0]^.typ=top_reg) and
3718                  (oper[1]^.typ=top_reg) and
3719                  (oper[0]^.reg=oper[1]^.reg)
3720                 ) or
3721                 ({ checking the opcodes is a long "or" chain, so check first the registers which is more selective }
3722                  ((regtype = R_MMREGISTER) and
3723                   (ops=2) and
3724                   (oper[0]^.typ=top_reg) and
3725                   (oper[1]^.typ=top_reg) and
3726                   (oper[0]^.reg=oper[1]^.reg)) and
3727                   (
3728                    (opcode=A_MOVSS) or (opcode=A_MOVSD) or
3729                    (opcode=A_MOVQ) or (opcode=A_MOVD) or
3730                    (opcode=A_MOVAPS) or (opcode=A_MOVAPD) or
3731                    (opcode=A_MOVUPS) or (opcode=A_MOVUPD) or
3732                    (opcode=A_MOVDQA) or (opcode=A_MOVDQU) or
3733                    (opcode=A_VMOVSS) or (opcode=A_VMOVSD) or
3734                    (opcode=A_VMOVQ) or (opcode=A_VMOVD) or
3735                    (opcode=A_VMOVAPS) or (opcode=A_VMOVAPD) or
3736                    (opcode=A_VMOVUPS) or (opcode=A_VMOVUPD) or
3737                    (opcode=A_VMOVDQA) or (opcode=A_VMOVDQU)
3738                   )
3739                 );
3740       end;
3741 
3742 
3743     procedure build_spilling_operation_type_table;
3744       var
3745         opcode : tasmop;
3746         i      : integer;
3747       begin
3748         new(operation_type_table);
3749         fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
3750         for opcode:=low(tasmop) to high(tasmop) do
3751           with InsProp[opcode] do
3752           begin
3753               if Ch_Rop1 in Ch then
3754                     operation_type_table^[opcode,0]:=operand_read;
3755               if Ch_Wop1 in Ch then
3756                     operation_type_table^[opcode,0]:=operand_write;
3757               if [Ch_RWop1,Ch_Mop1]*Ch<>[] then
3758                     operation_type_table^[opcode,0]:=operand_readwrite;
3759               if Ch_Rop2 in Ch then
3760                     operation_type_table^[opcode,1]:=operand_read;
3761               if Ch_Wop2 in Ch then
3762                     operation_type_table^[opcode,1]:=operand_write;
3763               if [Ch_RWop2,Ch_Mop2]*Ch<>[] then
3764                     operation_type_table^[opcode,1]:=operand_readwrite;
3765               if Ch_Rop3 in Ch then
3766                     operation_type_table^[opcode,2]:=operand_read;
3767               if Ch_Wop3 in Ch then
3768                     operation_type_table^[opcode,2]:=operand_write;
3769               if [Ch_RWop3,Ch_Mop3]*Ch<>[] then
3770                     operation_type_table^[opcode,2]:=operand_readwrite;
3771               if Ch_Rop4 in Ch then
3772                 operation_type_table^[opcode,3]:=operand_read;
3773               if Ch_Wop4 in Ch then
3774                 operation_type_table^[opcode,3]:=operand_write;
3775               if [Ch_RWop4,Ch_Mop4]*Ch<>[] then
3776                 operation_type_table^[opcode,3]:=operand_readwrite;
3777                 end;
3778               end;
3779 
3780 
taicpu.spilling_get_operation_typenull3781     function taicpu.spilling_get_operation_type(opnr: longint): topertype;
3782       begin
3783         { the information in the instruction table is made for the string copy
3784           operation MOVSD so hack here (FK)
3785 
3786           VMOVSS and VMOVSD has two and three operand flavours, this cannot modelled by x86ins.dat
3787           so fix it here (FK)
3788         }
3789         if ((opcode=A_MOVSD) or (opcode=A_VMOVSS) or (opcode=A_VMOVSD)) and (ops=2) then
3790           begin
3791             case opnr of
3792               0:
3793                 result:=operand_read;
3794               1:
3795                 result:=operand_write;
3796               else
3797                 internalerror(200506055);
3798             end
3799           end
3800         { IMUL has 1, 2 and 3-operand forms }
3801         else if opcode=A_IMUL then
3802           begin
3803             case ops of
3804               1:
3805                 if opnr=0 then
3806                   result:=operand_read
3807                 else
3808                   internalerror(2014011802);
3809               2:
3810                 begin
3811                   case opnr of
3812                     0:
3813                       result:=operand_read;
3814                     1:
3815                       result:=operand_readwrite;
3816                     else
3817                       internalerror(2014011803);
3818                   end;
3819                 end;
3820               3:
3821                 begin
3822                   case opnr of
3823                     0,1:
3824                       result:=operand_read;
3825                     2:
3826                       result:=operand_write;
3827                     else
3828                       internalerror(2014011804);
3829                   end;
3830                 end;
3831               else
3832                 internalerror(2014011805);
3833             end;
3834           end
3835         else
3836           result:=operation_type_table^[opcode,opnr];
3837       end;
3838 
3839 
spilling_create_loadnull3840     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
3841       var
3842         tmpref: treference;
3843       begin
3844         tmpref:=ref;
3845 {$ifdef i8086}
3846         if tmpref.segment=NR_SS then
3847           tmpref.segment:=NR_NO;
3848 {$endif i8086}
3849         case getregtype(r) of
3850           R_INTREGISTER :
3851             begin
3852               if getsubreg(r)=R_SUBH then
3853                 inc(tmpref.offset);
3854               { we don't need special code here for 32 bit loads on x86_64, since
3855                 those will automatically zero-extend the upper 32 bits. }
3856               result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),tmpref,r);
3857             end;
3858           R_MMREGISTER :
3859             if current_settings.fputype in fpu_avx_instructionsets then
3860               case getsubreg(r) of
3861                 R_SUBMMD:
3862                   result:=taicpu.op_ref_reg(A_VMOVSD,S_NO,tmpref,r);
3863                 R_SUBMMS:
3864                   result:=taicpu.op_ref_reg(A_VMOVSS,S_NO,tmpref,r);
3865                 R_SUBQ,
3866                 R_SUBMMWHOLE:
3867                   result:=taicpu.op_ref_reg(A_VMOVQ,S_NO,tmpref,r);
3868                 else
3869                   internalerror(200506043);
3870               end
3871             else
3872               case getsubreg(r) of
3873                 R_SUBMMD:
3874                   result:=taicpu.op_ref_reg(A_MOVSD,S_NO,tmpref,r);
3875                 R_SUBMMS:
3876                   result:=taicpu.op_ref_reg(A_MOVSS,S_NO,tmpref,r);
3877                 R_SUBQ,
3878                 R_SUBMMWHOLE:
3879                   result:=taicpu.op_ref_reg(A_MOVQ,S_NO,tmpref,r);
3880                 else
3881                   internalerror(200506043);
3882               end;
3883           else
3884             internalerror(200401041);
3885         end;
3886       end;
3887 
3888 
spilling_create_storenull3889     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
3890       var
3891         size: topsize;
3892         tmpref: treference;
3893       begin
3894         tmpref:=ref;
3895 {$ifdef i8086}
3896         if tmpref.segment=NR_SS then
3897           tmpref.segment:=NR_NO;
3898 {$endif i8086}
3899         case getregtype(r) of
3900           R_INTREGISTER :
3901             begin
3902               if getsubreg(r)=R_SUBH then
3903                 inc(tmpref.offset);
3904               size:=reg2opsize(r);
3905 {$ifdef x86_64}
3906               { even if it's a 32 bit reg, we still have to spill 64 bits
3907                 because we often perform 64 bit operations on them }
3908               if (size=S_L) then
3909                 begin
3910                   size:=S_Q;
3911                   r:=newreg(getregtype(r),getsupreg(r),R_SUBWHOLE);
3912                 end;
3913 {$endif x86_64}
3914               result:=taicpu.op_reg_ref(A_MOV,size,r,tmpref);
3915             end;
3916           R_MMREGISTER :
3917             if current_settings.fputype in fpu_avx_instructionsets then
3918               case getsubreg(r) of
3919                 R_SUBMMD:
3920                   result:=taicpu.op_reg_ref(A_VMOVSD,S_NO,r,tmpref);
3921                 R_SUBMMS:
3922                   result:=taicpu.op_reg_ref(A_VMOVSS,S_NO,r,tmpref);
3923                 R_SUBQ,
3924                 R_SUBMMWHOLE:
3925                   result:=taicpu.op_reg_ref(A_VMOVQ,S_NO,r,tmpref);
3926                 else
3927                   internalerror(200506042);
3928               end
3929             else
3930               case getsubreg(r) of
3931                 R_SUBMMD:
3932                   result:=taicpu.op_reg_ref(A_MOVSD,S_NO,r,tmpref);
3933                 R_SUBMMS:
3934                   result:=taicpu.op_reg_ref(A_MOVSS,S_NO,r,tmpref);
3935                 R_SUBQ,
3936                 R_SUBMMWHOLE:
3937                   result:=taicpu.op_reg_ref(A_MOVQ,S_NO,r,tmpref);
3938                 else
3939                   internalerror(200506042);
3940               end;
3941           else
3942             internalerror(200401041);
3943         end;
3944       end;
3945 
3946 
3947 {$ifdef i8086}
3948     procedure taicpu.loadsegsymbol(opidx:longint;s:tasmsymbol);
3949       var
3950         r: treference;
3951       begin
3952         reference_reset_symbol(r,s,0,1,[]);
3953         r.refaddr:=addr_seg;
3954         loadref(opidx,r);
3955       end;
3956 {$endif i8086}
3957 
3958 {*****************************************************************************
3959                               Instruction table
3960 *****************************************************************************}
3961 
3962     procedure BuildInsTabCache;
3963       var
3964         i : longint;
3965       begin
3966         new(instabcache);
3967         FillChar(instabcache^,sizeof(tinstabcache),$ff);
3968         i:=0;
3969         while (i<InsTabEntries) do
3970          begin
3971            if InsTabCache^[InsTab[i].OPcode]=-1 then
3972             InsTabCache^[InsTab[i].OPcode]:=i;
3973            inc(i);
3974          end;
3975       end;
3976 
3977 
3978     procedure BuildInsTabMemRefSizeInfoCache;
3979     var
3980       AsmOp: TasmOp;
3981       i,j: longint;
3982       insentry  : PInsEntry;
3983       MRefInfo: TMemRefSizeInfo;
3984       SConstInfo: TConstSizeInfo;
3985       actRegSize: int64;
3986       actMemSize: int64;
3987       actConstSize: int64;
3988       actRegCount: integer;
3989       actMemCount: integer;
3990       actConstCount: integer;
3991       actRegTypes  : int64;
3992       actRegMemTypes: int64;
3993       NewRegSize: int64;
3994 
3995       actVMemCount  : integer;
3996       actVMemTypes  : int64;
3997 
3998       RegMMXSizeMask: int64;
3999       RegXMMSizeMask: int64;
4000       RegYMMSizeMask: int64;
4001 
4002       bitcount: integer;
4003 
bitcntnull4004       function bitcnt(aValue: int64): integer;
4005       var
4006         i: integer;
4007       begin
4008         result := 0;
4009 
4010         for i := 0 to 63 do
4011         begin
4012           if (aValue mod 2) = 1 then
4013           begin
4014             inc(result);
4015           end;
4016 
4017           aValue := aValue shr 1;
4018         end;
4019       end;
4020 
4021     begin
4022       new(InsTabMemRefSizeInfoCache);
4023       FillChar(InsTabMemRefSizeInfoCache^,sizeof(TInsTabMemRefSizeInfoCache),0);
4024 
4025       for AsmOp := low(TAsmOp) to high(TAsmOp) do
4026       begin
4027         i := InsTabCache^[AsmOp];
4028 
4029         if i >= 0 then
4030         begin
4031           InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize   := msiUnkown;
4032           InsTabMemRefSizeInfoCache^[AsmOp].ConstSize    := csiUnkown;
4033           InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := false;
4034 
4035           insentry:=@instab[i];
4036           RegMMXSizeMask := 0;
4037           RegXMMSizeMask := 0;
4038           RegYMMSizeMask := 0;
4039 
4040           while (insentry^.opcode=AsmOp) do
4041           begin
4042             MRefInfo         := msiUnkown;
4043 
4044             actRegSize       := 0;
4045             actRegCount      := 0;
4046             actRegTypes      := 0;
4047             NewRegSize       := 0;
4048 
4049             actMemSize       := 0;
4050             actMemCount      := 0;
4051             actRegMemTypes   := 0;
4052 
4053             actVMemCount     := 0;
4054             actVMemTypes     := 0;
4055 
4056             actConstSize     := 0;
4057             actConstCount    := 0;
4058 
4059             for j := 0 to insentry^.ops -1 do
4060             begin
4061               if ((insentry^.optypes[j] and OT_XMEM32) = OT_XMEM32) OR
4062                  ((insentry^.optypes[j] and OT_XMEM64) = OT_XMEM64) OR
4063                  ((insentry^.optypes[j] and OT_YMEM32) = OT_YMEM32) OR
4064                  ((insentry^.optypes[j] and OT_YMEM64) = OT_YMEM64) then
4065               begin
4066                 inc(actVMemCount);
4067 
4068                 case insentry^.optypes[j] and (OT_XMEM32 OR OT_XMEM64 OR OT_YMEM32 OR OT_YMEM64) of
4069                   OT_XMEM32: actVMemTypes := actVMemTypes or OT_XMEM32;
4070                   OT_XMEM64: actVMemTypes := actVMemTypes or OT_XMEM64;
4071                   OT_YMEM32: actVMemTypes := actVMemTypes or OT_YMEM32;
4072                   OT_YMEM64: actVMemTypes := actVMemTypes or OT_YMEM64;
4073                         else InternalError(777206);
4074                 end;
4075               end
4076               else if (insentry^.optypes[j] and OT_REGISTER) = OT_REGISTER then
4077               begin
4078                 inc(actRegCount);
4079 
4080                   NewRegSize := (insentry^.optypes[j] and OT_SIZE_MASK);
4081                   if NewRegSize = 0 then
4082                     begin
4083                       case insentry^.optypes[j] and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_REG_EXTRA_MASK) of
4084                         OT_MMXREG: begin
4085                                      NewRegSize := OT_BITS64;
4086                                    end;
4087                         OT_XMMREG: begin
4088                                      NewRegSize := OT_BITS128;
4089                                      InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
4090                                    end;
4091                         OT_YMMREG: begin
4092                                      NewRegSize := OT_BITS256;
4093                                      InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
4094                                    end;
4095                               else NewRegSize := not(0);
4096                       end;
4097                   end;
4098 
4099                 actRegSize  := actRegSize or NewRegSize;
4100                 actRegTypes := actRegTypes or (insentry^.optypes[j] and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_REG_EXTRA_MASK));
4101                 end
4102               else if ((insentry^.optypes[j] and OT_MEMORY) <> 0) then
4103                 begin
4104                   inc(actMemCount);
4105 
4106                   actMemSize:=actMemSize or (insentry^.optypes[j] and OT_SIZE_MASK);
4107                   if (insentry^.optypes[j] and OT_REGMEM) = OT_REGMEM then
4108                     begin
4109                       actRegMemTypes  := actRegMemTypes or insentry^.optypes[j];
4110                     end;
4111                 end
4112               else if ((insentry^.optypes[j] and OT_IMMEDIATE) = OT_IMMEDIATE) then
4113               begin
4114                 inc(actConstCount);
4115 
4116                 actConstSize    := actConstSize or (insentry^.optypes[j] and OT_SIZE_MASK);
4117               end
4118             end;
4119 
4120             if actConstCount > 0 then
4121             begin
4122               case actConstSize of
4123                 0: SConstInfo := csiNoSize;
4124                 OT_BITS8: SConstInfo := csiMem8;
4125                 OT_BITS16: SConstInfo := csiMem16;
4126                 OT_BITS32: SConstInfo := csiMem32;
4127                 OT_BITS64: SConstInfo := csiMem64;
4128                 else SConstInfo := csiMultiple;
4129               end;
4130 
4131               if InsTabMemRefSizeInfoCache^[AsmOp].ConstSize = csiUnkown then
4132               begin
4133                 InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := SConstInfo;
4134               end
4135               else if InsTabMemRefSizeInfoCache^[AsmOp].ConstSize <> SConstInfo then
4136               begin
4137                 InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := csiMultiple;
4138               end;
4139             end;
4140 
4141             if actVMemCount > 0 then
4142             begin
4143               if actVMemCount = 1 then
4144               begin
4145                 if actVMemTypes > 0 then
4146                 begin
4147                   case actVMemTypes of
4148                     OT_XMEM32: MRefInfo := msiXMem32;
4149                     OT_XMEM64: MRefInfo := msiXMem64;
4150                     OT_YMEM32: MRefInfo := msiYMem32;
4151                     OT_YMEM64: MRefInfo := msiYMem64;
4152                           else InternalError(777208);
4153                   end;
4154 
4155                   case actRegTypes of
4156                     OT_XMMREG: case MRefInfo of
4157                                  msiXMem32,
4158                                  msiXMem64: RegXMMSizeMask := RegXMMSizeMask or OT_BITS128;
4159                                  msiYMem32,
4160                                  msiYMem64: RegXMMSizeMask := RegXMMSizeMask or OT_BITS256;
4161                                        else InternalError(777210);
4162                                end;
4163                     OT_YMMREG: case MRefInfo of
4164                                  msiXMem32,
4165                                  msiXMem64: RegYMMSizeMask := RegYMMSizeMask or OT_BITS128;
4166                                  msiYMem32,
4167                                  msiYMem64: RegYMMSizeMask := RegYMMSizeMask or OT_BITS256;
4168                                        else InternalError(777211);
4169                                end;
4170                           //else InternalError(777209);
4171                   end;
4172 
4173 
4174                   if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
4175                   begin
4176                     InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
4177                   end
4178                   else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
4179                   begin
4180                     if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize in [msiXMem32, msiXMem64, msiYMem32, msiYMem64] then
4181                     begin
4182                       InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiVMemMultiple;
4183                     end
4184                     else InternalError(777212);
4185                   end;
4186 
4187                 end;
4188               end
4189               else InternalError(777207);
4190             end
4191             else
4192               begin
4193                 if (actMemCount=2) and ((AsmOp=A_MOVS) or (AsmOp=A_CMPS)) then
4194                   actMemCount:=1;
4195             case actMemCount of
4196                 0: ; // nothing todo
4197                 1: begin
4198                      MRefInfo := msiUnkown;
4199                      case actRegMemTypes and (OT_MMXRM or OT_XMMRM or OT_YMMRM or OT_REG_EXTRA_MASK) of
4200                        OT_MMXRM: actMemSize := actMemSize or OT_BITS64;
4201                        OT_XMMRM: actMemSize := actMemSize or OT_BITS128;
4202                        OT_YMMRM: actMemSize := actMemSize or OT_BITS256;
4203                      end;
4204 
4205                      case actMemSize of
4206                        0: MRefInfo := msiNoSize;
4207                        OT_BITS8: MRefInfo := msiMem8;
4208                        OT_BITS16: MRefInfo := msiMem16;
4209                        OT_BITS32: MRefInfo := msiMem32;
4210                        OT_BITS64: MRefInfo := msiMem64;
4211                        OT_BITS128: MRefInfo := msiMem128;
4212                        OT_BITS256: MRefInfo := msiMem256;
4213                        OT_BITS80,
4214                        OT_FAR,
4215                        OT_NEAR,
4216                        OT_SHORT: ; // ignore
4217                        else
4218                          begin
4219                            bitcount := bitcnt(actMemSize);
4220 
4221                            if bitcount > 1 then MRefInfo := msiMultiple
4222                            else InternalError(777203);
4223                          end;
4224                      end;
4225 
4226                      if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
4227                        begin
4228                          InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
4229                        end
4230                      else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
4231                        begin
4232                          with InsTabMemRefSizeInfoCache^[AsmOp] do
4233                          begin
4234                            if ((MemRefSize = msiMem8)        OR (MRefInfo = msiMem8))   then MemRefSize := msiMultiple8
4235                            else if ((MemRefSize = msiMem16)  OR (MRefInfo = msiMem16))  then MemRefSize := msiMultiple16
4236                            else if ((MemRefSize = msiMem32)  OR (MRefInfo = msiMem32))  then MemRefSize := msiMultiple32
4237                            else if ((MemRefSize = msiMem64)  OR (MRefInfo = msiMem64))  then MemRefSize := msiMultiple64
4238                            else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
4239                            else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
4240                            else MemRefSize := msiMultiple;
4241                          end;
4242                      end;
4243 
4244                      if actRegCount > 0 then
4245                        begin
4246                          case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_REG_EXTRA_MASK) of
4247                            OT_MMXREG: RegMMXSizeMask := RegMMXSizeMask or actMemSize;
4248                            OT_XMMREG: RegXMMSizeMask := RegXMMSizeMask or actMemSize;
4249                            OT_YMMREG: RegYMMSizeMask := RegYMMSizeMask or actMemSize;
4250                                  else begin
4251                                         RegMMXSizeMask := not(0);
4252                                         RegXMMSizeMask := not(0);
4253                                         RegYMMSizeMask := not(0);
4254                                       end;
4255                          end;
4256                        end;
4257                    end;
4258               else InternalError(777202);
4259             end;
4260               end;
4261 
4262             inc(insentry);
4263           end;
4264 
4265           if (InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize in MemRefMultiples) and
4266              (InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX)then
4267           begin
4268             case RegXMMSizeMask of
4269               OT_BITS16: case RegYMMSizeMask of
4270                            OT_BITS32: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx16y32;
4271                         end;
4272                OT_BITS32: case RegYMMSizeMask of
4273                             OT_BITS64: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx32y64;
4274                          end;
4275                OT_BITS64: case RegYMMSizeMask of
4276                             OT_BITS128: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y128;
4277                             OT_BITS256: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y256;
4278                           end;
4279               OT_BITS128: begin
4280                             if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiVMemMultiple then
4281                             begin
4282                               // vector-memory-operand AVX2 (e.g. VGATHER..)
4283                               case RegYMMSizeMask of
4284                                 OT_BITS256: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiVMemRegSize;
4285                               end;
4286                             end
4287                             else if RegMMXSizeMask = 0 then
4288                             begin
4289                               case RegYMMSizeMask of
4290                                 OT_BITS128: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y128;
4291                                 OT_BITS256: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegSize;
4292                               end;
4293                             end
4294                             else if RegYMMSizeMask = 0 then
4295                             begin
4296                               case RegMMXSizeMask of
4297                                 OT_BITS64: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegSize;
4298                               end;
4299                             end
4300                             else InternalError(777205);
4301                           end;
4302             end;
4303           end;
4304         end;
4305       end;
4306 
4307       for AsmOp := low(TAsmOp) to high(TAsmOp) do
4308       begin
4309 
4310 
4311         // only supported intructiones with SSE- or AVX-operands
4312         if not(InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX) then
4313         begin
4314           InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize  := msiUnkown;
4315           InsTabMemRefSizeInfoCache^[AsmOp].ConstSize   := csiUnkown;
4316         end;
4317       end;
4318     end;
4319 
4320     procedure InitAsm;
4321       begin
4322         build_spilling_operation_type_table;
4323         if not assigned(instabcache) then
4324           BuildInsTabCache;
4325 
4326         if not assigned(InsTabMemRefSizeInfoCache) then
4327           BuildInsTabMemRefSizeInfoCache;
4328       end;
4329 
4330 
4331     procedure DoneAsm;
4332       begin
4333         if assigned(operation_type_table) then
4334           begin
4335             dispose(operation_type_table);
4336             operation_type_table:=nil;
4337           end;
4338         if assigned(instabcache) then
4339           begin
4340             dispose(instabcache);
4341             instabcache:=nil;
4342           end;
4343 
4344         if assigned(InsTabMemRefSizeInfoCache) then
4345         begin
4346           dispose(InsTabMemRefSizeInfoCache);
4347           InsTabMemRefSizeInfoCache:=nil;
4348         end;
4349       end;
4350 
4351 
4352 begin
4353   cai_align:=tai_align;
4354   cai_cpu:=taicpu;
4355 end.
4356