1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /** 18 * @author Alexander V. Astapchuk 19 */ 20 /** 21 * @file 22 * @brief Simple interface for generating processor instructions. 23 * 24 * The interface works for both IA32 and EM64T. By default, only IA32 25 * capabilities are presented. To enable EM64T feature, the _EM64T_ macro 26 * must be defined (and, of course, a proper library version to be used). 27 * 28 * The interface is based on the original ia32.h encoder interface, 29 * with some simplifications and add-ons - EM64T-specific, SSE and SSE2. 30 * 31 * The interface mostly intended for existing legacy code like LIL code 32 * generator. From the implementation point of view, it's just a wrapper 33 * around the EncoderBase functionality. 34 */ 35 36 #ifndef _VM_ENCODER_H_ 37 #define _VM_ENCODER_H_ 38 39 #include <limits.h> 40 #include "enc_base.h" 41 //#include "open/types.h" 42 43 #ifdef _EM64T_ 44 // size of general-purpose value on the stack in bytes 45 #define GR_STACK_SIZE 8 46 // size of floating-point value on the stack in bytes 47 #define FR_STACK_SIZE 8 48 49 #if defined(WIN32) || defined(_WIN64) 50 // maximum number of GP registers for inputs 51 const int MAX_GR = 4; 52 // maximum number of FP registers for inputs 53 const int MAX_FR = 4; 54 // WIN64 reserves 4 words for shadow space 55 const int SHADOW = 4 * GR_STACK_SIZE; 56 #else 57 // maximum number of GP registers for inputs 58 const int MAX_GR = 6; 59 // maximum number of FP registers for inputs 60 const int MAX_FR = 8; 61 // Linux x64 doesn't reserve shadow space 62 const int SHADOW = 0; 63 #endif 64 65 #else 66 // size of general-purpose value on the stack in bytes 67 #define GR_STACK_SIZE 4 68 // size of general-purpose value on the stack in bytes 69 #define FR_STACK_SIZE 8 70 71 // maximum number of GP registers for inputs 72 const int MAX_GR = 0; 73 // maximum number of FP registers for inputs 74 const int MAX_FR = 0; 75 #endif 76 77 typedef enum Reg_No { 78 #ifdef _EM64T_ 79 rax_reg = 0,rbx_reg, rcx_reg, rdx_reg, 80 rdi_reg, rsi_reg, rsp_reg, rbp_reg, 81 r8_reg, r9_reg, r10_reg, r11_reg, 82 r12_reg, r13_reg, r14_reg, r15_reg, 83 xmm0_reg, xmm1_reg, xmm2_reg, xmm3_reg, 84 xmm4_reg, xmm5_reg, xmm6_reg, xmm7_reg, 85 xmm8_reg, xmm9_reg, xmm10_reg, xmm11_reg, 86 xmm12_reg, xmm13_reg, xmm14_reg, xmm15_reg, 87 88 #else // !defined(_EM64T_) 89 90 eax_reg = 0,ebx_reg, ecx_reg, edx_reg, 91 edi_reg, esi_reg, esp_reg, ebp_reg, 92 xmm0_reg, xmm1_reg, xmm2_reg, xmm3_reg, 93 xmm4_reg, xmm5_reg, xmm6_reg, xmm7_reg, 94 fs_reg, 95 #endif 96 /** @brief Total number of registers.*/ 97 n_reg 98 } Reg_No; 99 // 100 // instruction operand sizes: 8,16,32,64 bits 101 // 102 typedef enum Opnd_Size { 103 size_8 = 0, 104 size_16, 105 size_32, 106 size_64, 107 n_size, 108 #ifdef _EM64T_ 109 size_platf = size_64 110 #else 111 size_platf = size_32 112 #endif 113 } Opnd_Size; 114 115 // 116 // opcodes for alu instructions 117 // 118 typedef enum ALU_Opcode { 119 add_opc = 0,or_opc, adc_opc, sbb_opc, 120 and_opc, sub_opc, xor_opc, cmp_opc, 121 n_alu 122 } ALU_Opcode; 123 124 // 125 // opcodes for shift instructions 126 // 127 typedef enum Shift_Opcode { 128 shld_opc, shrd_opc, shl_opc, shr_opc, 129 sar_opc, ror_opc, max_shift_opcode=6, n_shift = 6 130 } Shift_Opcode; 131 132 typedef enum ConditionCode { 133 Condition_O = 0, 134 Condition_NO = 1, 135 Condition_B = 2, 136 Condition_NAE = Condition_B, 137 Condition_C = Condition_B, 138 Condition_NB = 3, 139 Condition_AE = Condition_NB, 140 Condition_NC = Condition_NB, 141 Condition_Z = 4, 142 Condition_E = Condition_Z, 143 Condition_NZ = 5, 144 Condition_NE = Condition_NZ, 145 Condition_BE = 6, 146 Condition_NA = Condition_BE, 147 Condition_NBE = 7, 148 Condition_A = Condition_NBE, 149 150 Condition_S = 8, 151 Condition_NS = 9, 152 Condition_P = 10, 153 Condition_PE = Condition_P, 154 Condition_NP = 11, 155 Condition_PO = Condition_NP, 156 Condition_L = 12, 157 Condition_NGE = Condition_L, 158 Condition_NL = 13, 159 Condition_GE = Condition_NL, 160 Condition_LE = 14, 161 Condition_NG = Condition_LE, 162 Condition_NLE = 15, 163 Condition_G = Condition_NLE, 164 Condition_Count = 16 165 } ConditionCode; 166 167 // 168 // prefix code 169 // 170 typedef enum InstrPrefix { 171 no_prefix, 172 lock_prefix = 0xF0, 173 hint_branch_taken_prefix = 0x2E, 174 hint_branch_not_taken_prefix = 0x3E, 175 prefix_repne = 0xF2, 176 prefix_repnz = prefix_repne, 177 prefix_repe = 0xF3, 178 prefix_repz = prefix_repe, 179 prefix_rep = 0xF3, 180 prefix_cs = 0x2E, 181 prefix_ss = 0x36, 182 prefix_ds = 0x3E, 183 prefix_es = 0x26, 184 prefix_fs = 0x64, 185 prefix_gs = 0x65 186 } InstrPrefix; 187 188 189 // 190 // an instruction operand 191 // 192 class Opnd { 193 194 protected: 195 enum Tag { SignedImm, UnsignedImm, Reg, Mem, FP, XMM }; 196 197 const Tag tag; 198 Opnd(Tag t)199 Opnd(Tag t): tag(t) {} 200 201 public: new(size_t,void * mem)202 void * operator new(size_t, void * mem) { 203 return mem; 204 } 205 delete(void *)206 void operator delete(void *) {} 207 delete(void *,void *)208 void operator delete(void *, void *) {} 209 210 private: 211 // disallow copying Opnd(const Opnd &)212 Opnd(const Opnd &): tag(Mem) { assert(false); } 213 Opnd& operator=(const Opnd &) { assert(false); return *this; } 214 }; 215 typedef int I_32; 216 class Imm_Opnd: public Opnd { 217 218 protected: 219 union { 220 #ifdef _EM64T_ 221 int64 value; 222 unsigned char bytes[8]; 223 #else 224 I_32 value; 225 unsigned char bytes[4]; 226 #endif 227 }; 228 Opnd_Size size; 229 230 public: 231 Imm_Opnd(I_32 val, bool isSigned = true): 232 Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(size_32) { 233 if (isSigned) { 234 if (CHAR_MIN <= val && val <= CHAR_MAX) { 235 size = size_8; 236 } else if (SHRT_MIN <= val && val <= SHRT_MAX) { 237 size = size_16; 238 } 239 } else { 240 assert(val >= 0); 241 if (val <= UCHAR_MAX) { 242 size = size_8; 243 } else if (val <= USHRT_MAX) { 244 size = size_16; 245 } 246 } 247 } Imm_Opnd(const Imm_Opnd & that)248 Imm_Opnd(const Imm_Opnd& that): Opnd(that.tag), value(that.value), size(that.size) {}; 249 250 #ifdef _EM64T_ 251 Imm_Opnd(Opnd_Size sz, int64 val, bool isSigned = true): 252 Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) { 253 #ifndef NDEBUG 254 switch (size) { 255 case size_8: 256 assert(val == (int64)(I_8)val); 257 break; 258 case size_16: 259 assert(val == (int64)(int16)val); 260 break; 261 case size_32: 262 assert(val == (int64)(I_32)val); 263 break; 264 case size_64: 265 break; 266 case n_size: 267 assert(false); 268 break; 269 } 270 #endif // NDEBUG 271 } 272 get_value()273 int64 get_value() const { return value; } 274 275 #else 276 277 Imm_Opnd(Opnd_Size sz, I_32 val, int isSigned = true): 278 Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) { 279 #ifndef NDEBUG 280 switch (size) { 281 case size_8: 282 assert((I_32)val == (I_32)(I_8)val); 283 break; 284 case size_16: 285 assert((I_32)val == (I_32)(int16)val); 286 break; 287 case size_32: 288 break; 289 case size_64: 290 case n_size: 291 assert(false); 292 break; 293 } 294 #endif // NDEBUG 295 } 296 get_value()297 I_32 get_value() const { return value; } 298 299 #endif get_size()300 Opnd_Size get_size() const { return size; } is_signed()301 bool is_signed() const { return tag == SignedImm; } 302 }; 303 304 class RM_Opnd: public Opnd { 305 306 public: is_reg()307 bool is_reg() const { return tag != SignedImm && tag != UnsignedImm && tag != Mem; } 308 309 protected: RM_Opnd(Tag t)310 RM_Opnd(Tag t): Opnd(t) {} 311 312 private: 313 // disallow copying RM_Opnd(const RM_Opnd &)314 RM_Opnd(const RM_Opnd &): Opnd(Reg) { assert(false); } 315 }; 316 317 class R_Opnd: public RM_Opnd { 318 319 protected: 320 Reg_No _reg_no; 321 322 public: R_Opnd(Reg_No r)323 R_Opnd(Reg_No r): RM_Opnd(Reg), _reg_no(r) {} reg_no()324 Reg_No reg_no() const { return _reg_no; } 325 326 private: 327 // disallow copying R_Opnd(const R_Opnd &)328 R_Opnd(const R_Opnd &): RM_Opnd(Reg) { assert(false); } 329 }; 330 331 // 332 // a memory operand with displacement 333 // Can also serve as a full memory operand with base,index, displacement and scale. 334 // Use n_reg to specify 'no register', say, for index. 335 class M_Opnd: public RM_Opnd { 336 337 protected: 338 Imm_Opnd m_disp; 339 Imm_Opnd m_scale; 340 R_Opnd m_index; 341 R_Opnd m_base; 342 343 public: 344 //M_Opnd(Opnd_Size sz): RM_Opnd(Mem, K_M, sz), m_disp(0), m_scale(0), m_index(n_reg), m_base(n_reg) {} M_Opnd(I_32 disp)345 M_Opnd(I_32 disp): 346 RM_Opnd(Mem), m_disp(disp), m_scale(0), m_index(n_reg), m_base(n_reg) {} M_Opnd(Reg_No rbase,I_32 rdisp)347 M_Opnd(Reg_No rbase, I_32 rdisp): 348 RM_Opnd(Mem), m_disp(rdisp), m_scale(0), m_index(n_reg), m_base(rbase) {} M_Opnd(I_32 disp,Reg_No rbase,Reg_No rindex,unsigned scale)349 M_Opnd(I_32 disp, Reg_No rbase, Reg_No rindex, unsigned scale): 350 RM_Opnd(Mem), m_disp(disp), m_scale(scale), m_index(rindex), m_base(rbase) {} M_Opnd(const M_Opnd & that)351 M_Opnd(const M_Opnd & that) : RM_Opnd(Mem), 352 m_disp((int)that.m_disp.get_value()), m_scale((int)that.m_scale.get_value()), 353 m_index(that.m_index.reg_no()), m_base(that.m_base.reg_no()) 354 {} 355 // base(void)356 inline const R_Opnd & base(void) const { return m_base; } index(void)357 inline const R_Opnd & index(void) const { return m_index; } scale(void)358 inline const Imm_Opnd & scale(void) const { return m_scale; } disp(void)359 inline const Imm_Opnd & disp(void) const { return m_disp; } 360 }; 361 362 // 363 // a memory operand with base register and displacement 364 // 365 class M_Base_Opnd: public M_Opnd { 366 367 public: M_Base_Opnd(Reg_No base,I_32 disp)368 M_Base_Opnd(Reg_No base, I_32 disp) : M_Opnd(disp, base, n_reg, 0) {} 369 370 private: 371 // disallow copying - but it leads to ICC errors #734 in encoder.inl 372 // M_Base_Opnd(const M_Base_Opnd &): M_Opnd(0) { assert(false); } 373 }; 374 375 // 376 // a memory operand with base register, scaled index register 377 // and displacement. 378 // 379 class M_Index_Opnd : public M_Opnd { 380 381 public: M_Index_Opnd(Reg_No base,Reg_No index,I_32 disp,unsigned scale)382 M_Index_Opnd(Reg_No base, Reg_No index, I_32 disp, unsigned scale): 383 M_Opnd(disp, base, index, scale) {} 384 385 private: 386 // disallow copying - but it leads to ICC errors #734 in encoder.inl 387 // M_Index_Opnd(const M_Index_Opnd &): M_Opnd(0) { assert(false); } 388 }; 389 390 class XMM_Opnd : public Opnd { 391 392 protected: 393 unsigned m_idx; 394 395 public: XMM_Opnd(unsigned _idx)396 XMM_Opnd(unsigned _idx): Opnd(XMM), m_idx(_idx) {}; get_idx(void)397 unsigned get_idx( void ) const { return m_idx; }; 398 399 private: 400 // disallow copying XMM_Opnd(const XMM_Opnd &)401 XMM_Opnd(const XMM_Opnd &): Opnd(XMM) { assert(false); } 402 }; 403 404 // 405 // operand structures for ia32 registers 406 // 407 #ifdef _EM64T_ 408 409 extern R_Opnd rax_opnd; 410 extern R_Opnd rcx_opnd; 411 extern R_Opnd rdx_opnd; 412 extern R_Opnd rbx_opnd; 413 extern R_Opnd rdi_opnd; 414 extern R_Opnd rsi_opnd; 415 extern R_Opnd rsp_opnd; 416 extern R_Opnd rbp_opnd; 417 418 extern R_Opnd r8_opnd; 419 extern R_Opnd r9_opnd; 420 extern R_Opnd r10_opnd; 421 extern R_Opnd r11_opnd; 422 extern R_Opnd r12_opnd; 423 extern R_Opnd r13_opnd; 424 extern R_Opnd r14_opnd; 425 extern R_Opnd r15_opnd; 426 427 extern XMM_Opnd xmm8_opnd; 428 extern XMM_Opnd xmm9_opnd; 429 extern XMM_Opnd xmm10_opnd; 430 extern XMM_Opnd xmm11_opnd; 431 extern XMM_Opnd xmm12_opnd; 432 extern XMM_Opnd xmm13_opnd; 433 extern XMM_Opnd xmm14_opnd; 434 extern XMM_Opnd xmm15_opnd; 435 #else 436 437 extern R_Opnd eax_opnd; 438 extern R_Opnd ecx_opnd; 439 extern R_Opnd edx_opnd; 440 extern R_Opnd ebx_opnd; 441 extern R_Opnd esp_opnd; 442 extern R_Opnd ebp_opnd; 443 extern R_Opnd esi_opnd; 444 extern R_Opnd edi_opnd; 445 446 #endif // _EM64T_ 447 448 extern XMM_Opnd xmm0_opnd; 449 extern XMM_Opnd xmm1_opnd; 450 extern XMM_Opnd xmm2_opnd; 451 extern XMM_Opnd xmm3_opnd; 452 extern XMM_Opnd xmm4_opnd; 453 extern XMM_Opnd xmm5_opnd; 454 extern XMM_Opnd xmm6_opnd; 455 extern XMM_Opnd xmm7_opnd; 456 457 #ifdef NO_ENCODER_INLINE 458 #define ENCODER_DECLARE_EXPORT 459 #else 460 #define ENCODER_DECLARE_EXPORT inline 461 #include "encoder.inl" 462 #endif 463 464 // prefix 465 ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p); 466 467 // stack push and pop instructions 468 ENCODER_DECLARE_EXPORT char * push(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 469 ENCODER_DECLARE_EXPORT char * push(char * stream, const Imm_Opnd & imm); 470 ENCODER_DECLARE_EXPORT char * pop(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 471 472 // cmpxchg or xchg 473 ENCODER_DECLARE_EXPORT char * cmpxchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); 474 ENCODER_DECLARE_EXPORT char * xchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); 475 476 // inc(rement), dec(rement), not, neg(ate) instructions 477 ENCODER_DECLARE_EXPORT char * inc(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 478 ENCODER_DECLARE_EXPORT char * dec(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 479 ENCODER_DECLARE_EXPORT char * _not(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 480 ENCODER_DECLARE_EXPORT char * neg(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 481 ENCODER_DECLARE_EXPORT char * nop(char * stream); 482 ENCODER_DECLARE_EXPORT char * int3(char * stream); 483 484 // alu instructions: add, or, adc, sbb, and, sub, xor, cmp 485 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 486 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf); 487 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 488 489 // test instruction 490 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 491 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); 492 493 // shift instructions: shl, shr, sar, shld, shrd, ror 494 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 495 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, Opnd_Size sz = size_platf); 496 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 497 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); 498 499 // multiply instructions: mul, imul 500 ENCODER_DECLARE_EXPORT char * mul(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 501 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 502 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 503 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, const Imm_Opnd& imm, Opnd_Size sz = size_platf); 504 505 // divide instructions: div, idiv 506 ENCODER_DECLARE_EXPORT char * idiv(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 507 508 // data movement: mov 509 ENCODER_DECLARE_EXPORT char * mov(char * stream, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf); 510 ENCODER_DECLARE_EXPORT char * mov(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 511 ENCODER_DECLARE_EXPORT char * mov(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); 512 513 ENCODER_DECLARE_EXPORT char * movsx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 514 ENCODER_DECLARE_EXPORT char * movzx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 515 516 ENCODER_DECLARE_EXPORT char * movd(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm); 517 ENCODER_DECLARE_EXPORT char * movd(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm); 518 ENCODER_DECLARE_EXPORT char * movq(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm); 519 ENCODER_DECLARE_EXPORT char * movq(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm); 520 521 // sse mov 522 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 523 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const M_Opnd & mem, const XMM_Opnd & xmm, bool dbl); 524 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 525 526 // sse add, sub, mul, div 527 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 528 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 529 530 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 531 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 532 533 ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 534 ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 535 536 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 537 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 538 539 // xor, compare 540 ENCODER_DECLARE_EXPORT char * sse_xor(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); 541 542 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 543 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem, bool dbl); 544 545 // sse conversions 546 ENCODER_DECLARE_EXPORT char * sse_cvt_si(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); 547 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const M_Opnd & mem, bool dbl); 548 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const XMM_Opnd & xmm, bool dbl); 549 ENCODER_DECLARE_EXPORT char * sse_cvt_fp2dq(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 550 ENCODER_DECLARE_EXPORT char * sse_cvt_dq2fp(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); 551 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem64); 552 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); 553 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem32); 554 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); 555 556 // condition operations 557 ENCODER_DECLARE_EXPORT char * cmov(char * stream, ConditionCode cc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); 558 ENCODER_DECLARE_EXPORT char * setcc(char * stream, ConditionCode cc, const RM_Opnd & rm8); 559 560 // load effective address: lea 561 ENCODER_DECLARE_EXPORT char * lea(char * stream, const R_Opnd & r, const M_Opnd & m, Opnd_Size sz = size_platf); 562 ENCODER_DECLARE_EXPORT char * cdq(char * stream); 563 ENCODER_DECLARE_EXPORT char * wait(char * stream); 564 565 // control-flow instructions 566 ENCODER_DECLARE_EXPORT char * loop(char * stream, const Imm_Opnd & imm); 567 568 // jump with 8-bit relative 569 ENCODER_DECLARE_EXPORT char * jump8(char * stream, const Imm_Opnd & imm); 570 571 // jump with 32-bit relative 572 ENCODER_DECLARE_EXPORT char * jump32(char * stream, const Imm_Opnd & imm); 573 574 // register indirect jump 575 ENCODER_DECLARE_EXPORT char * jump(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 576 577 // jump to target address 578 ENCODER_DECLARE_EXPORT char *jump(char * stream, char *target); 579 580 // jump with displacement 581 //char * jump(char * stream, I_32 disp); 582 583 // conditional branch with 8-bit branch offset 584 ENCODER_DECLARE_EXPORT char * branch8(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix); 585 586 // conditional branch with 32-bit branch offset 587 ENCODER_DECLARE_EXPORT char * branch32(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix); 588 589 // conditional branch with target label address 590 //char * branch(char * stream, ConditionCode cc, const char * target, InstrPrefix prefix = no_prefix); 591 592 // conditional branch with displacement immediate 593 ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, I_32 disp, InstrPrefix prefix = no_prefix); 594 595 // call with displacement 596 ENCODER_DECLARE_EXPORT char * call(char * stream, const Imm_Opnd & imm); 597 598 // indirect call through register or memory location 599 ENCODER_DECLARE_EXPORT char * call(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); 600 601 // call target address 602 ENCODER_DECLARE_EXPORT char * call(char * stream, const char * target); 603 604 // return instruction 605 ENCODER_DECLARE_EXPORT char * ret(char * stream); 606 ENCODER_DECLARE_EXPORT char * ret(char * stream, unsigned short pop); 607 ENCODER_DECLARE_EXPORT char * ret(char * stream, const Imm_Opnd & imm); 608 609 // string operations 610 ENCODER_DECLARE_EXPORT char * set_d(char * stream, bool set); 611 ENCODER_DECLARE_EXPORT char * scas(char * stream, unsigned char prefix); 612 ENCODER_DECLARE_EXPORT char * stos(char * stream, unsigned char prefix); 613 614 // floating-point instructions 615 616 // st(0) = st(0) fp_op m{32,64}real 617 //!char * fp_op_mem(char * stream, FP_Opcode opc,const M_Opnd& mem,int is_double); 618 619 // st(0) = st(0) fp_op st(i) 620 //!char *fp_op(char * stream, FP_Opcode opc,unsigned i); 621 622 // st(i) = st(i) fp_op st(0) ; optionally pop stack 623 //!char * fp_op(char * stream, FP_Opcode opc,unsigned i,unsigned pop_stk); 624 625 // compare st(0),st(1) and pop stack twice 626 //!char * fcompp(char * stream); 627 ENCODER_DECLARE_EXPORT char * fldcw(char * stream, const M_Opnd & mem); 628 ENCODER_DECLARE_EXPORT char * fnstcw(char * stream, const M_Opnd & mem); 629 ENCODER_DECLARE_EXPORT char * fnstsw(char * stream); 630 //!char * fchs(char * stream); 631 //!char * frem(char * stream); 632 //!char * fxch(char * stream,unsigned i); 633 //!char * fcomip(char * stream, unsigned i); 634 635 // load from memory (as fp) into fp register stack 636 ENCODER_DECLARE_EXPORT char * fld(char * stream, const M_Opnd & m, bool is_double); 637 //!char *fld80(char * stream,const M_Opnd& mem); 638 639 // load from memory (as int) into fp register stack 640 //!char * fild(char * stream,const M_Opnd& mem,int is_long); 641 642 // push st(i) onto fp register stack 643 //!char * fld(char * stream,unsigned i); 644 645 // push the constants 0.0 and 1.0 onto the fp register stack 646 //!char * fldz(char * stream); 647 //!char * fld1(char * stream); 648 649 // store stack to memory (as int), always popping the stack 650 ENCODER_DECLARE_EXPORT char * fist(char * stream, const M_Opnd & mem, bool is_long, bool pop_stk); 651 // store stack to to memory (as fp), optionally popping the stack 652 ENCODER_DECLARE_EXPORT char * fst(char * stream, const M_Opnd & m, bool is_double, bool pop_stk); 653 // store ST(0) to ST(i), optionally popping the stack. Takes 1 clock 654 ENCODER_DECLARE_EXPORT char * fst(char * stream, unsigned i, bool pop_stk); 655 656 //!char * pushad(char * stream); 657 //!char * pushfd(char * stream); 658 //!char * popad(char * stream); 659 //!char * popfd(char * stream); 660 661 // stack frame allocation instructions: enter & leave 662 // 663 // enter frame_size 664 // 665 // is equivalent to: 666 // 667 // push ebp 668 // mov ebp,esp 669 // sub esp,frame_size 670 // 671 //!char *enter(char * stream,const Imm_Opnd& imm); 672 673 // leave 674 // is equivalent to: 675 // 676 // mov esp,ebp 677 // pop ebp 678 //!char *leave(char * stream); 679 680 // sahf loads SF, ZF, AF, PF, and CF flags from eax 681 //!char *sahf(char * stream); 682 683 // Intrinsic FP math functions 684 685 //!char *math_fsin(char * stream); 686 //!char *math_fcos(char * stream); 687 //!char *math_fabs(char * stream); 688 //!char *math_fpatan(char * stream); 689 ENCODER_DECLARE_EXPORT char * fprem(char * stream); 690 ENCODER_DECLARE_EXPORT char * fprem1(char * stream); 691 //!char *math_frndint(char * stream); 692 //!char *math_fptan(char * stream); 693 694 // 695 // Add 1-7 bytes padding, with as few instructions as possible, 696 // with no effect on the processor state (e.g., registers, flags) 697 // 698 //!char *padding(char * stream, unsigned num); 699 700 // prolog and epilog code generation 701 //- char *prolog(char * stream,unsigned frame_size,unsigned reg_save_mask); 702 //- char *epilog(char * stream,unsigned reg_save_mask); 703 704 //!extern R_Opnd reg_operand_array[]; 705 706 // fsave and frstor 707 //!char *fsave(char * stream); 708 //!char *frstor(char * stream); 709 710 // lahf : Load Status Flags into AH Register 711 //!char *lahf(char * stream); 712 713 // mfence : Memory Fence 714 //!char *mfence(char * stream); 715 716 #endif // _VM_ENCODER_H_ 717