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